Оригинал статьи.
AngularJS имеет простой способ взаимодействия с внешними API. В этой статье я рассмотрю, как использовать службы для доступа к API GitHub и создам простой обозреватель репозитория.
Шаг 1: Подготовка
Начну с простого HTML шаблона:
<!DOCTYPE html>
<html>
<head>
<title>GitHub Search</title>
</head>
<body>
</body>
</html>
Добавлю AngularJS в head шаблона:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
Немного CSS:
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
font-family: sans-serif;
}
body, html { margin: 0; }
p { margin: 0; }
input { width: 100%; }
pre {
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
}
div.repo {
border-bottom: 1px solid;
cursor: pointer;
}
#search, #repo, #user { float: left; }
#search { width: 20%; }
#repo { width: 60%; }
#user { width: 20%; }
Шаг 2: Модуль
Модуль приложения:
var app = angular.module('githubsearch', []);
Добавлю его в шаблон с помощью директивы ngApp:
<body ng-app="githubsearch">
Шаг 3: Контроллер
Мне также понадобится контроллер для этого приложения. Для простоты, это будет один контролер для всего приложения, по этому мне не придется иметь дело с передачей информации между контроллерами:
app.controller('SearchController', function SearchController($scope) {
});
Шаг 4: Базовая служба
Определю базовую службу:
app.factory('GitHub', function GitHub($http) {
return {
};
});
Я использую метод app.factory()
, чтобы просто вернуть объект с несколькими методами и использовать их позже. Я буду использовать $http для получения данных из API GitHub.
Шаг 5: Поиск репозитория
Первый метод в моем сервисе будет поиск репозитория с использованием API GitHub. Использование $http сервиса довольно просто (эта функция переходит в объект возвращенного нашей функции фабрики):
searchRepos: function searchRepos(query, callback) {
$http.get('https://api.github.com/search/repositories', { params: { q: query } })
.success(function (data) {
callback(null, data);
})
.error(function (e) {
callback(e);
});
}
Метод $http.get()
является сокращением от запросы GET. Первый параметр является URL, к которуму я хочу получить доступ. Второй является объектом с параметрами. Мне нужно только params
объекта — это хэш параметров запроса, которые будут добавлены к запросу (параметр q
является строкой поиска, как описано здесь).
$http.get()
возвращает promise. Можно использовать success()
и error ()
слушателей и вызвать соответствующую функцию.
Шаг 6: Блок поиска
Чтобы воспользоваться функцией, которую я создал в предыдущем шаге необходимо добавить поле поиска в html шаблон:
<div ng-controller="SearchController">
<div id="search">
<input ng-model="query" placeholder="search" ng-keyup="$event.keyCode == 13 && executeSearch()">
<div class="repo" ng-repeat="repo in repos" ng-click="openRepo(repo.full_name)">
<strong>{{ repo.full_name }}</strong>
<p>{{ repo.description }}</p>
</div>
</div>
</div>
Я использую директиву ngModel
для связи значение этого поля и переменную query
и ngKeyup
для вызова функцию executeSearch()
, когда пользователь нажмет клавишу enter ($event.keyCode == 13)
. Использовать условные операторы в выражениях AngularJS нельзя, но простая логика операций будет работать.
Под полем ввода, я используя ngRepeat
для отображения результатов поиска. Я буду выводить полное имя репозитория и описание (можно выводить разные данные, полный список можно посмотреть в API GitHub).
Я также используем ngClick
для вызова функцию openRepo()
с полным описанием репозитория. Эту функция описана далее.
Шаг 7: Использование функции поиска
Теперь добавлю параметр GitHub к функции контроллера:
app.controller('SearchController', function SearchController($scope,GitHub) {
Функция executeSearch()
:
$scope.executeSearch = function executeSearch() {
GitHub.searchRepos($scope.query, function (error, data) {
if (!error) {
$scope.repos = data.items;
}
});
}
Я вызываю метод GitHub.searchRepos()
с параметром поиска $scope.query
и помещаю результаты поиска (data.items
) в переменную $scope.repos
.
Это все, что нужно для вывода результатов поиска. Демо.
Шаг 8: Получение информации о репозитории
Теперь, когда есть функция поиска можно вывести информацию о выбранном репозитории:
getRepo: function getRepo(name, callback) {
$http.get('https://api.github.com/repos/'+ name)
.success(function (data) {
callback(null, data);
})
.error(function (e) {
callback(e);
});
}
Название передаваемое в эту функцию должно быть полным именем (имя автора, слэш, имя репозитория — например: angular/angular.js), так как оно будет передано в API GitHub.
Шаг 9: Получение из репозитория README файл
Содержание файл README получу не в предыдущей функции, а в отдельной:
getReadme: function getReadme(name, callback) {
$http.get('https://api.github.com/repos/'+ name +'/readme')
.success(function (data) {
callback(null, atob(data.content));
})
.error(function (e) {
callback(e);
});
}
Эта и предыдущая функция почти идентичны, только изменен URL. Еще использую функцию atob()
, чтобы декодировать содержимое файла README, так как он кодирован в кодировке base64. Получение содержимого файла README описывается здесь.
Я не использовали два запроса в одной функции так как некоторые репозитории нет README файла.
Шаг 10: Отображение информации о репозитории
Я буду отображать полное имя репозитория, количество людей посмотревших его и файл README:
<div id="repo" ng-show="activeRepo">
<strong>{{ activeRepo.full_name }}</strong> <em>Watched by {{ activeRepo.watchers_count }} people.</em>
<pre>{{ activeRepo.readme }}</pre>
</div>
Хранить эту информацию я буду в переменной activeRepo
. Директива ngShow
покажет элемент, только если в нем есть данные.
Шаг 11: Обновление контроллера
Также необходимо обновить контроллер. Функция openRepo(), которую я повесил на директиву ngClick выше:
$scope.openRepo = function openRepo(name) {
GitHub.getRepo(name, function (error, data) {
if (!error) {
$scope.activeRepo = data;
GitHub.getReadme(name, function (error, data) {
if (!error) {
$scope.activeRepo.readme = data;
} else {
$scope.activeRepo.readme = 'No README found!';
}
});
}
});
}
Cначала я использую метод GitHub.getRepo()
, для проверки на наличие ошибок, а затем помещаю данные в переменной activeRepo. После этого я и получаю файл README.
Автор: romasport