Статьи

Создание веб-приложения с нуля в AngularJS

В предыдущем уроке по AngularJS я рассмотрел все основы того, как начать работу с Angular примерно за 30 минут. В этом уроке мы расскажем о том, что там было написано, создав простое реальное веб-приложение.

Это простое веб-приложение позволит пользователям просматривать, искать и фильтровать телешоу Premieres в течение следующих 30 дней. Как увлеченный зритель сериала, я всегда ищу что-то новое, чтобы посмотреть, когда мои любимые шоу выходят в эфир, поэтому я решил создать приложение, которое поможет мне найти то, что я ищу.

Прежде чем мы начнем, вы можете взглянуть на демонстрацию сверху, чтобы увидеть, что мы будем создавать в этом уроке. Также ознакомьтесь с подборкой полезных скриптов и утилит AngularJS на Envato Market, чтобы увидеть, что вы можете найти для своих собственных проектов.


Для начала нам понадобится скелетное приложение AngularJS, в котором уже есть все необходимые JavaScript и CSS для создания приложения TV Show Premieres. Загрузите этот скелет с помощью кнопки «Скачать исходные файлы» выше.

После того, как вы загрузили файлы, у вас должна быть структура каталогов, как показано ниже:

Figure1-каркасно-каталог-структура

Изучив структуру каталогов и включенные файлы, вы увидите, что мы будем использовать Twitter Bootstrap, чтобы сделать наше веб-приложение более привлекательным, но в этом руководстве мы не будем рассматривать Twitter Bootstrap более подробно (узнайте больше о Twitter Bootstrap ). Кроме того, в этом руководстве не будет рассказано, как настроить новое приложение AngularJS, так как вышеупомянутое руководство AngularJS уже подробно описывает это.

После открытия index.html вашем браузере вы должны увидеть очень простую веб-страницу с заголовком и базовым форматированием, как показано ниже:

Figure2 основного веб-страниц

Первое, что нам понадобится для создания нашего приложения для телешоу, это информация о телешоу. Мы собираемся использовать API, предоставленный Trakt.tv. Прежде чем мы начнем, вам понадобится ключ API, вы можете зарегистрировать его на их веб-сайте .

Зачем использовать этот API? Я действительно должен зарегистрироваться? Мы используем этот API, поэтому наше приложение будет использовать реальные данные и фактически предоставит некоторое использование после завершения. Кроме того, с помощью этого API нам не нужно проходить через какие-либо реализации на стороне сервера в этом руководстве, и мы можем полностью сосредоточиться на AngularJS. Дополнительная пара минут для регистрации в API будет стоить того.

Теперь, когда у вас есть собственный ключ API, мы можем использовать Trakt API для получения информации о телешоу. Мы собираемся использовать один из доступных вызовов API для этого урока, более подробную информацию об этом можно найти в api docs . Этот вызов API предоставит нам все премьеры телешоу в указанные сроки.

Откройте mainController.js и измените его в соответствии с приведенным ниже кодом:

Если вы index.html файл index.html , найдите следующую строку:

1
<div class=»container main-frame» ng-app=»TVPremieresApp» ng-controller=»mainController» ng-init=»init()»>

Вы увидите, что метод ng-init вызывает функцию init , это означает, что функция init() в нашем mainController будет вызываться после загрузки страницы.

Если вы прочтете документацию по API для метода calendar/premieres вы увидите, что он принимает три параметра, ваш ключ API, дату начала (например, 20130616) и количество дней.

Чтобы предоставить все три параметра, нам сначала нужно получить сегодняшнюю дату с помощью метода JavaScripts Date() и отформатировать ее в указанном API-формате, чтобы создать строку apiDate . Теперь, когда у нас есть все, что нам нужно, мы можем создать вызов метода $http.jsonp для API. Это позволит нашему веб-приложению вызывать URL-адрес, который находится за пределами нашего собственного домена, и получать некоторые данные JSON. Убедитесь, что ?callback=JSON_CALLBACK добавлен к URI запроса, чтобы наша присоединенная .success обратного вызова .success была вызвана при ответе.

В нашей функции .success мы просто .success полученные данные на консоль. Откройте index.html в вашем браузере и откройте консоль JavaScript, вы должны увидеть что-то вроде следующего:

Рисунок 3-Javascript-консоль

Это показывает, что мы успешно выполняем вызов API Trakt, аутентифицируемся с помощью нашего ключа API и получаем некоторые данные JSON. Теперь, когда у нас есть данные телешоу, мы можем перейти к следующему шагу.


Прежде чем мы сможем отобразить наши данные, нам нужно обработать и сохранить их. Поскольку API возвращает премьерные эпизоды, сгруппированные по дате, мы хотим удалить эту группировку и просто создать единый массив со всеми премьерными эпизодами и связанными с ними данными. Измените mainController.js следующим образом:

Приведенный выше код хорошо прокомментирован и должен быть легок для понимания, давайте посмотрим на эти изменения. Сначала мы объявляем переменную области $scope.results как массив, который будет содержать наши обработанные результаты. Затем мы используем angular.forEach (который аналогичен методу $.each в jQuery для тех, кто его знает), чтобы $.each каждую группу дат и сохранить дату в локальной переменной date .

Затем мы создаем еще один цикл, который перебирает каждое из телешоу в этой группе дат, добавляет локально сохраненную дату в объект tvshow а затем, наконец, добавляет каждый объект $scope.results массив $scope.results . После всего этого наш массив $scope.results будет выглядеть следующим образом:

figure4 отформатированные-tvshow-JSON-объекты

Теперь у нас есть некоторые данные, которые мы хотим отобразить в списке на нашей странице. Мы можем создать некоторый HTML с помощью ng-repeat для динамического создания элементов списка на основе данных в $scope.results . Добавьте следующий HTML-код в неупорядоченный список с классом episode-list в index.html :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<li ng-repeat=»tvshow in results»>
       <div class=»row-fluid»>
           <div class=»span3″>
               <img src=»{{tvshow.episode.images.screen}}» />
               <div class=»ratings»><strong>Ratings:</strong> <span class=»label»><i class=»icon-thumbs-up»></i> {{tvshow.episode.ratings.loved}}
           </div>
           <div class=»span6″>
               <h3>{{tvshow.show.title}}: {{tvshow.episode.title}}</h3>
               <p>{{tvshow.episode.overview}}</p>
           </div>
           <div class=»span3″>
               <div class=»fulldate pull-right label label-info»>{{tvshow.date}}</div>
               <ul class=»show-info»>
                   <li><strong>On Air:</strong> {{tvshow.show.air_day}} {{tvshow.show.air_time}}</li>
                   <li><strong>Network:</strong> {{tvshow.show.network}}</li>
                   <li><strong>Season #:</strong> {{tvshow.episode.season}}</li>
                   <li><strong>Genres:</strong> <span class=»label label-inverse genre» ng-repeat=»genre in tvshow.show.genres»>{{genre}}
               </ul>
           </div>
       </div>
   </li>

Этот HTML просто создает один элемент списка с помощью ng-repeat . ng-repeat="tvshow in results" говорит угловому повторить этот элемент списка для каждого объекта в массиве $scope.results . Помните, что нам не нужно включать $scope , так как мы находимся внутри элемента с указанным контроллером (подробнее об этом см. В предыдущем руководстве).

Внутри элемента li мы можем ссылаться на tvshow как на переменную, которая будет содержать все данные объектов для каждого из телешоу в $scope.results . Ниже приведен пример одного из объектов в $scope.results так что вы можете легко увидеть, как ссылаться на каждый фрагмент данных:

Например, в элементе li мы можем получить заголовок шоу, tvshow.show.title и tvshow.show.title его в двойные фигурные скобки: {{ }} . При таком понимании должно быть легко увидеть, какая информация будет отображаться для каждого элемента списка. Благодаря CSS в комплекте со структурой скелета, если вы сохраните эти изменения и откроете index.html в своем браузере, вы должны увидеть красиво отформатированный список ТВ-шоу со связанной информацией и изображениями. Это показано на рисунке ниже:

figure5 в формате шоу-список

Вы можете или не могли заметить:

1
ng-class=»{‘label-success’: tvshow.episode.ratings.percentage >= 50}»

… который прикреплен к одному из элементов span в разделе оценок в приведенном выше HTML. ng-class позволяет нам условно применять классы к элементам HTML. Это особенно полезно здесь, поскольку мы можем затем применить другой стиль к элементу процентного span зависимости от того, высокий процент рейтинга ТВ-шоу или нет.

В приведенном выше примере HTML мы хотим применить класс label-success , который является классом Twitter Bootstrap, который будет стилизовать диапазон, чтобы иметь зеленый фон и белый текст. Мы хотим применить этот класс к элементу, только если процент рейтинга больше или равен 50. Мы можем сделать это так же просто, как tvshow.episode.ratings.percentage >= 50 . Посмотрите список форматированных телепередач в вашем браузере. Если какой-либо процент соответствует этому условию, он должен отображаться зеленым цветом.


Теперь у нас есть список предстоящих премьер ТВ-шоу, и это здорово, но не так много в плане функциональности. Теперь мы собираемся добавить простой текстовый поиск, который будет фильтровать все объекты в массиве результатов.

Во-первых, нам нужно объявить переменную $scope.filterText в mainController.js следующим образом:

Теперь нам нужно добавить текстовый ввод, чтобы пользователь мог фактически ввести поисковый запрос. Затем нам нужно привязать этот ввод к вновь объявленной переменной. Добавьте следующий HTML- div в div который имеет класс search-box в index.html .

1
2
<label>Filter: </label>
   <input type=»text» ng-model=»filterText»/>

Здесь мы использовали ng-model для привязки этого ввода к переменной $scope.filterText мы объявили в нашей области видимости. Теперь эта переменная всегда будет равна тому, что вводится в этот поисковый ввод.

Теперь, когда у нас есть текст для фильтрации, нам нужно добавить функцию фильтрации в ng-repeat . Благодаря встроенной функции фильтрации AngularJS нам не нужно писать какой-либо JavaScript для этого, просто измените ваш ng-repeat следующим образом:

1
<li ng-repeat=»tvshow in results | filter: filterText»>

Это так просто! Мы говорим AngularJS — прежде чем выводить данные с помощью ng-repeat , нам нужно применить фильтр на основе переменной filterText. Откройте index.html в браузере и выполните поиск. Предполагая, что вы искали что-то существующее, вы должны увидеть выборку результатов.


Таким образом, наши пользователи теперь могут искать то, что хотят посмотреть, что лучше, чем просто статичный список телепередач. Но мы можем немного расширить функциональность нашего фильтра и создать собственный фильтр, который позволит пользователю выбирать определенный жанр. После выбора определенного жанра ng-repeat должен отображать только телешоу с выбранным жанром.

Прежде всего, добавьте следующий HTML- filterText в filterText ввода filterText в index.html который мы добавили ранее.

1
2
3
4
<label>Genre: </label>
   <select ng-model=»genreFilter» ng-options=»label for label in availableGenres»>
       <option value=»»>All</option>
   </select>

Из приведенного выше HTML-кода видно, что мы создали входные данные select, привязанные к переменной модели под названием genreFilter . Используя ng-options мы можем динамически заполнять этот выбор, используя массив с именем availableGenres .

Прежде всего, нам нужно объявить эти переменные области видимости. Обновите файл mainController.js следующим образом:

Очевидно, что теперь мы объявили и genreFilter и availableGenres которые мы ссылались в нашем HTML. Мы также добавили немного JavaScript, который будет заполнять наш массив availableGenres . В рамках функции init() , пока мы обрабатываем данные JSON, возвращаемые из API, мы сейчас выполняем некоторую дополнительную обработку и добавляем в этот массив все жанры, которых еще нет в массиве availableGenres . Затем он заполнит выбранный вход любыми доступными жанрами.

Если вы откроете index.html в своем браузере, вы увидите раскрывающийся список выбора жанра, как показано ниже:

figure6-жанр выберите падение вниз

Когда пользователь выбирает жанр, переменная $scope.genreFilter будет обновлена ​​в соответствии с выбранным значением.

Поскольку мы хотим фильтровать определенную часть объектов телешоу, мы собираемся создать собственную функцию фильтра и применить ее вместе с фильтром AngularJS в ng-repeat .

В самом низу mainController.js после всего остального кода добавьте следующий JavaScript:

Приведенный выше JavaScript объявляет пользовательский фильтр для нашего приложения isGenre . Функция в фильтре принимает два параметра, input и genre . input предоставляется по умолчанию (что мы увидим чуть позже) и представляет собой все данные, которые обрабатывает ng-repeat . genre — это значение, которое мы должны передать. Все, что делает этот фильтр, это берет указанный жанр и проверяет, имеет ли каждый из объектов телешоу во input файле указанный жанр, прикрепленный к ним. Если объект имеет указанный жанр, он добавляет его в массив out , который затем будет возвращен в ng-repeat . Если это не имеет смысла, не волнуйтесь! Стоит в ближайшее время.

Теперь, когда у нас есть доступ к нашему фильтру клиентов, мы можем добавить этот дополнительный фильтр к нашему ng-repeat. Измените ваш ng-repeat в index.html следующим образом:

1
<li ng-repeat=»tvshow in results | filter: filterText | isGenre:genreFilter»>

Это просто связывает другой фильтр с выходом ng-repeat . Теперь вывод будет обработан обоими фильтрами, прежде чем он будет отображен на экране. Как вы можете видеть, мы указали наш пользовательский фильтр как isGenre: и затем мы genreFilter переменную области действия genreFilter в качестве параметра, и именно так мы предоставляем нашему клиентскому фильтру переменную genre мы говорили ранее. Помните, что AngularJS также предоставляет нашему фильтру данные, которые ng-repeat обрабатывает в качестве input переменной.

ОК, наш пользовательский жанровый фильтр завершен. Откройте index.html в браузере и протестируйте новые функции. С этим фильтром пользователь может легко отфильтровать жанры, которые ему не интересны.


Возможно, вы заметили, что каждый список телешоу также показывает сам жанр. Для некоторой дополнительной функциональности мы собираемся позволить пользователю выбирать эти жанры, чтобы затем автоматически применять жанровый фильтр для жанра, на который они нажали. Прежде всего, нам нужно создать функцию области видимости, которую может вызвать ng-click . Добавьте следующий код в mainController на mainController.js :

В приведенном выше коде эта функция принимает значение жанра, а затем устанавливает $scope.genreFilter в указанное значение. Когда это произойдет, значение окна выбора фильтра жанра будет обновлено, и фильтр будет применен к выводу ng-repeat . Чтобы активировать эту функцию при щелчке элементов диапазона жанра, добавьте ng-click к элементам диапазона жанра в index.html следующим образом:

1
<span class=»label label-inverse genre» ng-repeat=»genre in tvshow.show.genres» ng-click=»setGenreFilter(genre)»>{{genre}}

ng-click вызывает нашу ранее созданную функцию setGenreFilter и определяет жанр. Откройте index.html и попробуйте!


Наше приложение для премьеры ТВ-шоу выглядит довольно неплохо, пользователи могут легко уточнить результаты, отображаемые с помощью серии интуитивно понятных фильтров. Чтобы улучшить этот опыт, мы собираемся добавить некоторые пользовательские функции заказа, чтобы наши пользователи могли выбирать различные варианты заказа.

Добавьте следующий HTML-код под раскрывающийся список жанров:

1
2
3
4
5
6
<label>Order by: </label>
   <select ng-model=»orderField» ng-options=»label for label in orderFields» class=»input-medium»></select>
   <select ng-model=»orderReverse»class=»input-medium»>
       <option value=»true»>Descending</option>
       <option value=»false»>Ascending</option>
   </select>

После добавления этого кода у нас есть еще два раскрывающихся списка. Один, чтобы выбрать, как упорядочить данные, а другой, чтобы выбрать направление, в котором упорядочить данные. Теперь нам нужно создать функцию в нашем контроллере для сравнения заказов. Добавьте следующий JavaScript в нашу функцию setGenreFilter :

Нам также нужно объявить некоторые дополнительные переменные области видимости:

Если вы теперь откроете index.html в своем браузере, вы должны увидеть добавленные выпадающие списки, заполненные Air Date, уже выбранным в качестве поля заказа по умолчанию. Это показано на рисунке ниже:

figure7 заказ-выпадающие списки

Наконец, как мы сделали с другими нашими фильтрами, нам нужно добавить это в наш ng-repeat , обновив его следующим образом:

1
<li ng-repeat=»tvshow in results | filter: filterText | isGenre:genreFilter | orderBy:customOrder:orderReverse»>

В настоящее время мы применяем к каждому фильтру данные по фильтрам в дополнение к другим фильтрам. Мы customOrder заказу об использовании нашей функции orderReverse а также orderReverse переменную области видимости orderReverse . Откройте index.html в браузере и посмотрите порядок в действии.


AngularJS позволил нам быстро создать подробное и функциональное веб-приложение с минимальными усилиями. Используя встроенные функции фильтрации AngularJS, а также наш собственный код, наше веб-приложение позволяет нашим пользователям легко фильтровать и осуществлять поиск по премьерам телешоу.

После прочтения этого урока вы сможете понять и использовать следующие принципы:

  • Использование ng-repeat для отображения информации на экране.
  • Привязка к входам, позволяющая пользователям искать и фильтровать вывод ng-repeat .
  • Цепные фильтры в ng-repeat выполняют несколько функций фильтрации.
  • Индивидуальный заказ данных.
  • Использование событий, таких как ng-click для ответа на взаимодействие с пользователем.
  • Использование ng-class для условного применения стиля к элементам страницы.

Итак, в заключение, темы, рассматриваемые в этом руководстве, должны дать вам прочную основу и понимание того, чего вы можете достичь при создании многофункциональных веб-приложений в AngularJS.