Как создать приложение погоды с Angular, Bootstrap и API APIXU

Автор выбралNPower для получения пожертвования в рамках программыWrite for DOnations.

Вступление

Angular - это интерфейсный веб-фреймворк, созданный Google. Он позволяет разработчикам создавать одностраничные приложения, смоделированные на основе архитектурного шаблона программного обеспеченияmodel-view-controller (MVC) илиmodel-view-viewmodel (MVVM). Эта архитектура делит приложения на разные, но связанные части, позволяющие параллельную разработку. Следуя этому шаблону, Angular разделяет свои различные компоненты на соответствующие части веб-приложения. Его компоненты управляют данными и логикой, которые относятся к этому компоненту, отображают данные в соответствующем представлении и адаптируют или управляют представлением на основе различных сообщений, которые он получает от остальной части приложения.

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

APIXU предоставляет пользователям глобальные данные о погоде через свой API. Используя APIXU, пользователь может получать самую свежую погоду, а также прогнозы погоды на будущее в любой точке мира.

В этом руководстве вы создадите приложение погоды с помощью Angular, Bootstrap и API APIXU. Вы сможете ввести местоположение в форму поиска и, отправив эту форму, увидеть текущую информацию о погоде для этого местоположения в своем приложении. Версия Angular, используемая в этом руководстве, - 7.2.0, а версия Bootstrap - 4.2.1.

Предпосылки

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

[[step-1 -—- install-angular]] == Шаг 1. Установка Angular

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

npm install -g @angular/cli

Angular CLI - это интерфейс командной строки для Angular. Он служит основным способом создания нового проекта Angular, а также различных подэлементов, составляющих проект Angular. Использование аргумента-g установит его глобально.

Через некоторое время вы увидите следующий вывод:

Выход из установки Angular

...
+ @angular/[email protected]
...

Теперь вы установили Angular на свой локальный компьютер. Далее вы создадите свое угловое приложение.

[[step-2 -—- Creating-your-angular-app]] == Шаг 2. Создание приложения Angular

На этом этапе вы создадите и сконфигурируете свое новое приложение Angular, установите все его зависимости, такие как Bootstrap и jQuery, а затем, наконец, убедитесь, что приложение по умолчанию работает должным образом.

Сначала используйте командуng для создания приложения Angular, вы можете запустить его со своего терминала.

[.note] #Note: Если вы работаете в Windows, у вас могут возникнуть проблемы с попыткой запустить командуng из командной строки, даже если вы правильно установили Node.js и npm. Например, вы можете получить такую ​​ошибку:ng is not recognized as an internal or external command. Чтобы решить эту проблему, запустите командуng в установленной командной строке Node.js, расположенной в папке Node.js в Windows.
#

Командаng является предпосылкой для запуска любого действия с Angular из командной строки. Например, создаете ли вы новый проект, компоненты или тесты, перед каждой желаемой функциональностью вы ставите префикс командыng. В этом руководстве вы захотите создать новое приложение; вы добьетесь этого, выполнив командуng new. Командаng new создает новое приложение Angular, импортирует необходимые библиотеки и создает все стандартные шаблоны кода, которые требуются вашему приложению.

Начните с создания нового приложения, в этом руководстве оно будет называтьсяweather-app, но вы можете изменить имя по своему усмотрению:

ng new weather-app

Командаng new запросит у вас дополнительную информацию о функциях, которые вы хотите добавить в свое новое приложение.

OutputWould you like to add Angular routing? (y/N)

Angularrouting позволяет создавать одностраничные приложения с разными представлениями, используя маршруты и компоненты. Продолжайте и введитеy или нажмитеENTER, чтобы принять значения по умолчанию.

OutputWhich stylesheet format would you like to use? (Use arrow keys)

НажмитеENTER, чтобы принять параметр CSS по умолчанию.

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

Output...
CREATE weather-app/e2e/src/app.e2e-spec.ts (623 bytes)
CREATE weather-app/e2e/src/app.po.ts (204 bytes)
...
Successfully initialized git.

Затем в текстовом редакторе откройте папкуweather-app.

Рассматривая структуру вашего каталога, вы увидите несколько разных папок и файлов. Вы можете прочитать полное объяснение того, что делают все эти файлыhere, но для целей этого руководства это наиболее важные файлы, которые нужно понять:

  • Файлpackage.json. Расположенный в корневой папкеweather-app, он работает так же, как и любое другое приложение Node.js, хранит все библиотеки, которые ваше приложение будет использовать, имя вашего приложения, команды, запускаемые при тестировании, и так далее. В первую очередь этот файл содержит сведения о внешних библиотеках, которые необходимы вашему приложению Angular для правильной работы.

  • Файлapp.module.ts. Этот файл, расположенный в папкеapp внутри папкиweather-app/src, сообщает Angular, как собрать ваше приложение, и содержит подробную информацию о компонентах, модулях и поставщиках в вашем приложении. У вас уже есть импортированный модульBrowserModule в массивеimports. BrowserModule предоставляет важные службы и директивы для вашего приложения и всегда должен быть первым импортированным модулем в вашем массивеimports.

  • Файлangular.json. Этот файл конфигурации для Angular CLI находится в корневой папкеweather-app вашего приложения. Этот файл содержит настройки внутренней конфигурации того, что должно работать ваше приложение Angular. Он устанавливает значения по умолчанию для всего вашего приложения и имеет такие параметры, как, например, какие файлы конфигурации использовать при тестировании, какие глобальные стили использовать в вашем приложении или в какую папку выводить файлы сборки. Вы можете узнать больше об этих опциях в официальномAngular-CLI documentation.

Вы можете на время оставить все эти файлы в покое, так как затем вы установите Bootstrap.

У Bootstrap есть две зависимости, которые вам необходимо установить для правильной работы в Angular -jQuery иpopper.js. jQuery - это библиотека JavaScript, ориентированная на создание сценариев на стороне клиента, аpopper.js - это библиотека позиционирования, которая в основном управляет всплывающими подсказками и всплывающими окнами.

В вашем терминале перейдите в корневой каталогweather-app:

cd weather-app

Затем выполните следующую команду, чтобы установить все зависимости и сохранить ссылки в файлpackage.json:

npm install --save jquery popper.js bootstrap

Параметр--save автоматически импортирует ваши ссылки в файлpackage.json, поэтому вам не нужно добавлять их вручную после установки.

Вы увидите выходные данные с номерами версий, которые были установлены, например:

Вы успешно установили Bootstrap и его зависимости. Однако вам также необходимо включить эти библиотеки в ваше приложение. Вашweather-app еще не знает, что ему понадобятся эти библиотеки, поэтому вам нужно добавить пути кjquery,popper.js,bootstrap.js иbootstrap.css в ваш файлangular.json.

Дляpopper.js необходимо включить файлnode_modules/popper.js/dist/umd/popper.js. jQuery требует файлnode_modules/jquery/dist/jquery.slim.js. Наконец, для Bootstrap вам понадобятся два файла (и файл JavaScript, и файл CSS). Этоnode_modules/bootstrap/dist/js/bootstrap.js иnode_modules/bootstrap/dist/css/bootstrap.css соответственно.

Теперь, когда у вас есть все необходимые пути к файлам, откройте файлangular.json в текстовом редакторе. В массивstyles вы добавите ссылку на файлы CSS, а массивscripts будет ссылаться на все скрипты. Вы найдете оба этих массива в верхней части файлаangular.json в объекте JSON"options":. Добавьте следующий выделенный контент в файл:

angular.json

...
"options:" {
...
"styles": [
    "node_modules/bootstrap/dist/css/bootstrap.css",
     "src/styles.css"
],
"scripts": [
    "node_modules/jquery/dist/jquery.slim.js",
    "node_modules/popper.js/dist/umd/popper.js",
    "node_modules/bootstrap/dist/js/bootstrap.js"
]},
...

Вы импортировали основные файлы.js и.css, необходимые для правильной работы Bootstrap. Вы указали относительные пути к этим файлам из файлаangular.json: добавив файлы.css в массив стилей и файлы.js в массив скриптовangular.json. Убедитесь, что вы сохранили файлangular.json после добавления этого содержимого.

Теперь запустите приложение с помощью командыng serve, чтобы убедиться, что все работает правильно. Из каталогаweather-app в вашем терминале запустите:

ng serve --o

Аргумент--o автоматически откроет окно браузера, в котором будет отображаться ваше приложение. Сборка приложения займет несколько секунд, а затем отобразится в вашем браузере.

Вы увидите следующий вывод в своем терминале:

Output** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
...

После открытия браузера вы увидите страницу приложения Angular по умолчанию.

Image of default created app in Angular

Если вы не видите эти выходные данные, повторите этот шаг еще раз и убедитесь, что все правильно. Если вы видите ошибку, например:Port 4200 is already in use. Use '--port' to specify a different port, вы можете изменить номер порта, набрав:

ng serve --o --port 

Причина этого потенциального сообщения об ошибке заключается в том, что порт4200 на вашем компьютере используется другой программой или процессом. Вы можете либо, если вы знаете, что это за процесс, прекратить его, либо вы можете выполнить описанный выше шаг, чтобы указать другой номер порта.

Теперь вы настроили свои леса приложений. Затем вы создадите компонент погоды, который будет содержать основную форму и соответствующие сведения о погоде для местоположения поиска.

[[step-3 -—- Creating-your-weather-component]] == Шаг 3 - Создание вашего погодного компонента

Приложение Angular в основном состоит изcomponents, которые представляют собой части логики, выполняющие определенную функцию в приложении. Компонент состоит из некоторогоlogic, который управляет частью экрана в приложении - это называетсяview.

Например, в этом руководстве вы собираетесь создатьWeather Component, который будет отвечать за обработку двух задач:

  • Поиск места

  • Отображение связанных погодных данных для этого местоположения

Для достижения первой цели вы создадите форму, которая позволит вам искать местоположение. Когда вы нажимаете кнопку поиска в вашей форме, она запускает функцию, которая будет искать это местоположение.

Для достижения второй цели у вас будет<div> с вложенными тегами<p>, которые будут аккуратно отображать полученные вами данные.

Пока ваше приложение запускается из окна терминала, вы не можете ничего вводить в этом конкретном окне. Поэтому откройте каталогweather-app в новом окне терминала, если вы хотите выполнять другие командыng. Кроме того, вы можете остановить запуск приложения в исходном окне терминала, нажавCTRL + C. Затем вы можете установить новый компонент и после этого снова запустить приложение, набравng serve --o.

Выполните следующую команду, которая создаст вашWeather Component и автоматически импортирует его в ваш файлapp.module.ts. Помните, что ваш файлapp.module.ts содержит подробную информацию обо всех компонентах, модулях и поставщиках вашего приложения.

ng generate component weather

Вы увидите такой вывод (точные размеры байтов могут отличаться):

OutputCREATE src/app/weather/weather.component.css (0 bytes)
CREATE src/app/weather/weather.component.html (26 bytes)
CREATE src/app/weather/weather.component.spec.ts (635bytes)
CREATE src/app/weather/weather.component.ts (273 bytes)
UPDATE src/app/app.module.ts (400 bytes)
...

Эти выходные данные показывают, что Angular создал четыре файла, необходимые для компонента:

  • Файлы.css и.html для вашего представления

  • Файл.spec.ts для тестирования вашего компонента

  • Файл `.component.ts` для хранения функций вашего компонента.

Angular также обновил файлsrc/app/app.module.ts, чтобы добавить ссылку на вновь созданный компонент. Вы всегда найдете файлы компонентов в каталогеsrc/app/name-of-component.

Теперь, когда вы установили новый компонент, вернитесь в браузер, чтобы увидеть приложение. Если вы остановили приложение, запущенное для установки нового компонента, запустите его снова, набрав:

ng serve --o

Вы заметите, что вы все еще можете видеть «Добро пожаловать в приложение!» (Компонент по умолчанию), отображаемый на странице. Вы не можете видеть свой недавно созданный компонент. В следующем разделе вы измените это так, чтобы всякий раз, когда вы переходили кlocalhost:4200, вы получали доступ к только что созданному компоненту погоды вместо компонента Angular по умолчанию.

[[step-4 -—- accessing-your-weather-component]] == Шаг 4. Доступ к вашему компоненту погоды

В стандартном HTML всякий раз, когда вы хотите создать новую страницу, вы создаете новый файл.html. Например, если у вас уже была уже существующая HTML-страница, с которой вы хотите перейти на свою недавно созданную страницу, у вас будет атрибутhref с тегомanchor, указывающий на эту новую страницу. . Например:

preexisting.html

В Angular, однако, это работает немного по-другому. Вы не можете использовать атрибутhref таким образом для перехода к новому компоненту. Если вы хотите создать ссылку на компонент, вам нужно использовать библиотеку AngularRouter и объявить желаемый URL-путь в файле, который будет отображаться непосредственно на компонент.

В Angular вы называете этот файлroutes.ts. Здесь хранятся все детали ваших маршрутов (ссылки). Для правильной работы этого файла вы должны импортировать типRoutes из библиотеки@angular/router и указать желаемые ссылки типаRoutes. Это сообщит Angular, что это список маршрутов для навигации в вашем приложении.

Создайте файлroutes.ts в текстовом редакторе и сохраните его в каталогеsrc/app. Затем добавьте в файлroutes.ts следующее содержимое:

src/app/routes.ts

import { Routes } from '@angular/router'

Теперь объявите URL-путь и компонент вsrc/app/routes.ts. Вы хотите сделать свое приложение таким, чтобы при переходе на домашнюю страницу (http://localhost:4200) вы получали доступ к недавно созданному компоненту погоды. Добавьте эти строки в файл, который сопоставит корневой URL с только что созданным компонентом погоды:

src/app/routes.ts

import { Routes } from '@angular/router'
import { WeatherComponent } from './weather/weather.component';

export const allAppRoutes: Routes = [
  { path: '', component: WeatherComponent }
];

Вы импортировали свойWeatherComponent, а затем создали переменнуюallAppRoutes, которая представляет собой массив типаRoutes. МассивallAppRoutes содержит объекты определения маршрута, каждый из которых содержит путь URL и компонент для сопоставления. Вы указали, что каждый раз, когда вы переходите к корневому URL («), он должен переходить кWeatherComponent.

Ваш окончательный файлroutes.ts будет выглядеть так:

src/app/routes.ts

import { Routes } from "@angular/router";
import { WeatherComponent } from "./weather/weather.component";

export const allAppRoutes: Routes = [
  { path: '', component: WeatherComponent }
];

Теперь вам нужно добавить эти маршруты в ваш основной файлapp.module.ts. Вам нужно передать только что созданный массив -allAppRoutes - в модуль Angular, называемыйRouterModule. RouterModule инициализирует и настраивает маршрутизатор (отвечает за выполнение всей навигации приложения) и предоставляет ему свои данные маршрутизации изallAppRoutes. Добавьте следующий выделенный контент:

src/app/app.module.ts

...
import {WeatherComponent} from './weather/weather.component';
import {RouterModule} from '@angular/router';
import {allAppRoutes} from './routes';
...
@NgModule({
    declarations:[
      ...
    ],
    imports: [
        BrowserModule,
        RouterModule.forRoot(allAppRoutes)
    ]
    ...
})
...

В этом файле вы импортировали массивы объектов маршрутаRouterModule иallAppRoutes. Затем вы передали массивallAppRoutes в RouterModule, чтобы ваш маршрутизатор знал, куда направлять ваши URL-адреса.

Наконец, вам нужно включить саму маршрутизацию. Откройте файлapp.component.ts. Существует свойствоtemplateUrl, которое определяет HTML для этого конкретного компонента:./app.component.html. Откройте этот файл,src/app/app.component.html, и вы увидите, что он содержит весь HTML для вашей страницыlocalhost:4200.

Удалите весь HTML-код, содержащийся вapp.component.html, и замените его на:

src/app/app.component.html

Тегrouter-outlet активирует маршрутизацию и сопоставляет URL-адрес, который пользователь вводит в браузер, с определением маршрута, которое вы создали ранее в файлеroutes.ts в переменнойallAppRoutes. Затем маршрутизатор отображает представление в HTML. В этом руководстве вы отобразите кодweather.component.html сразу после тега<router-outlet></router-outlet>.

Теперь, если вы перейдете кhttp://localhost:4200, вы увидите, чтоweather works! появляется на вашей странице.

Вы настроили маршрутизацию в своем приложении. Затем вы создадите раздел формы и сведений, который позволит вам искать местоположение и показывать связанные с ним данные.

[[step-5 -—- defining-the-user-interface]] == Шаг 5 - Определение пользовательского интерфейса

Вы будете использовать Bootstrap в качестве основы для представления вашего приложения. Bootstrap полезен для создания готовых адаптивных веб-сайтов, которые адаптируются к любому устройству (мобильному, планшетному или настольному). Это достигается путем обработки каждой строки на веб-странице шириной в двенадцать столбцов. На веб-странице строка - это просто строка от одного конца страницы к другому. Это означает, что содержимое каждой страницы должно содержаться в этой строке, и оно должно равняться двенадцати столбцам. Если он не равен двенадцати столбцам, он будет перенесен в другой ряд. Например, в сеточной системе Bootstrap строка из двенадцати столбцов будет разделена на две части по шесть столбцов, а следующая строка из двенадцати столбцов будет разделена на три секции из четырех столбцов.

ВBootstrap documentation вы можете узнать больше об этой сеточной системе.

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

Откройтеsrc/app/weather/weather.component.html, чтобы получить доступ к вашему HTML-кодуWeatherComponent. Удалите абзац, который в данный момент находится в файле, а затем добавьте следующий код:

src/app/weather/weather.component.html

Search for Weather:

Weather Details:

Вы создали<div> с классомcontainer для хранения всего вашего контента. Затем вы создали строку, которую вы разбили на две части по шесть столбцов в каждой. Левая сторона будет содержать вашу форму поиска, а правая - данные о погоде.

Затем, чтобы создать форму, вы будете работать с первым столбцомcol-md-6. Вы также добавите кнопку, которая будет отправлять введенные вами данные в форму в APIXU, которая затем будет возвращать запрошенную информацию о погоде. Для этого определите первый классcol-md-6 и добавьте следующее выделенное содержимое под тегом<h3>:

src/app/weather/weather.component.html

...

Search for Weather:

...

Вы добавили форму и классform-group, который содержит панель поиска. Вы также создали свою кнопку для поиска погоды. В вашем браузере страница вашего приложения погоды будет выглядеть так:

Image of weather app page so far

Это выглядит немного компактно, так что вы можете добавить немного CSS, чтобы придать стилю страницы лучший интервал. Основным преимуществом Bootstrap является то, что он поставляется с интервалами классов, которые вы можете добавить в свой HTML без необходимости написания каких-либо дополнительных собственных CSS. Однако, если есть какой-то дополнительный CSS-код, который вы хотели бы включить в стандартные классы Bootstrap, который не распространяется, вы можете писать на своем собственном CSS-коде по мере необходимости. Для этого урока вы будете использовать стандартные классы Bootstrap.

Для каждого тега<h3> вы добавите CSS-класс Boostrap.my-4. m устанавливает маржу для элемента,y устанавливает какmargin-top, так иmargin-bottom для элемента, и, наконец,4 указывает размер добавляемой маржи. Вы можете узнать больше о различных типах и размерах интерваловhere. В вашем файлеweather.component.html добавьте следующее выделенное содержимое, чтобы заменить текущие теги<h3>:

src/app/weather/weather.component.html

Search for Weather:

Weather Details:

Перезагрузите страницу в своем браузере, и вы увидите, что у вас больше пробелов.

Image of spacing applied to weather app

Вы создали свою форму, а также раздел, в котором вы собираетесь отображать информацию, которую вы получаете от API APIXU. Затем вы подключите форму, чтобы иметь возможность правильно указать ваше местоположение.

[[step-6 -—- wiring-up-your-form]] == Шаг 6 - Подключение вашей формы

В Angular есть два способа создания форм для пользовательского ввода в вашем приложении -reactive илиtemplate-driven. Хотя они достигают одного и того же результата, каждый тип формы обрабатывает вводимые пользователем данные по-разному.

С реактивными формами вы создаете список различных элементов вашей формы в файле.component.ts. Затем вы подключаете их к созданной HTML-форме в соответствующем файле.component.html. Это строго в одну сторону; то есть данные передаются из вашего HTML в ваш файл.component.ts, двунаправленного потока данных нет.

С помощью шаблонно-управляемых форм вы создаете форму, как в обычном HTML. Затем, используя такие директивы, какngModel, вы можете создавать односторонние или двусторонние привязки данных из вашего HTML, обратно к вашей модели данных в вашем компоненте, и наоборот.

У каждого подхода есть свои сильные и слабые стороны, но в целом, реактивные формы предпочтительнее из-за:

  • Гибкость для создания форм различной сложности.

  • Простота модульного тестирования за счет проверки состояния каждого элемента управления формы в файле.component.ts компонента.

  • Возможностьsubscribe к значениям в форме. Разработчик может подписаться на поток создания ценности формы, позволяя ему выполнять некоторые действия со значениями, вводимыми в форму в режиме реального времени.

Несмотря на эти сильные стороны, реактивные формы иногда могут быть более сложными для реализации. Это может привести к тому, что разработчики будут писать больше кода, чем в форме на основе шаблонов Чтобы увидеть исчерпывающий обзор как типов форм, так и лучших вариантов использования,Angular’s official guide является хорошей отправной точкой. Для этого урока вы будете использовать реактивные формы.

Чтобы использовать реактивную форму, откройте файлapp.module.ts. Затем импортируйтеReactiveFormsModule, объявив импорт в верхней части файла.

src/app/app.module.ts

...
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
    ...
})
...

Наконец, добавьтеReactiveFormsModule в список импорта.

src/app/app.module.ts

...
@NgModule({
    ...
    imports: [
        BrowserModule,
        RouterModule.forRoot(allAppRoutes),
        ReactiveFormsModule
    ]
    ...
})
...

После этих добавлений кода вашapp.module.ts будет выглядеть так:

src/app/app.module.ts

import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";

import { AppComponent } from "./app.component";
import { WeatherComponent } from "./weather/weather.component";
import { RouterModule } from "@angular/router";
import { allAppRoutes } from "./routes";
import { ReactiveFormsModule } from "@angular/forms";

@NgModule({
  declarations: [AppComponent, WeatherComponent],
  imports: [
    BrowserModule,
    RouterModule.forRoot(allAppRoutes),
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

После того, как вы добавили обе эти строки, откройте файлweather.component.ts и импортируйте классыFormBuilder иFormGroup.

src/app/weather/weather.component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';

Теперь создайте переменную в вашем файлеweather.component.ts, которая будет ссылаться на вашFormGroup:

weather.component.ts

export class WeatherComponent implements OnInit {
   public weatherSearchForm: FormGroup;
   constructor() { }
...

Каждый раз, когда вы хотите выполнить действие в форме, вы будете ссылаться на него через переменнуюweatherSearchForm. Теперь вы добавите импортFormBuilder в вашconstructor, чтобы вы могли использовать его в своем компоненте.

weather.component.ts

...
public weatherSearchForm: FormGroup;
constructor(private formBuilder: FormBuilder) {}
...

ДобавляяformBuilder кconstructor, он создает экземпляр классаFormBuilder, что позволяет вам использовать его в своем компоненте.

Теперь вы готовы создать свойFormGroup и его соответствующие значения в файлеweather.component.ts. Если у вас есть несколько вариантов ввода в вашей форме, рекомендуется заключить их вFormGroup. В этом руководстве у вас будет только один (ввод вашего местоположения), но вы все равно будете использоватьFormGroupдля практики.

Важно, чтобы ваша форма была готова к использованию, когда вы переходите к своему компоненту. Поскольку вы используете реактивную форму, вы должны сначала создать дерево элементов внутри формы, прежде чем связывать его с HTML. Для этого вам необходимо убедиться, что вы создаете элементы формы в хукеngOnInit внутри вашегоWeatherComponent. МетодngOnInit запускается один раз при инициализации компонента, выполняя любую указанную вами логику, которую необходимо запустить до того, как компонент будет готов к использованию.

Поэтому вам необходимо создать свою форму, прежде чем вы сможете завершить привязку к процессу HTML.

В вашемWeatherComponent вы инициализируете форму с помощью хукаngOnInit:

src/app/weather/weather.component.ts

...
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
    this.weatherSearchForm = this.formBuilder.group({
      location: ['']
    });
  }

Вы создали первую часть формы в соответствии со стилем реактивной формы: определив компоненты формы в файлеweather.component.ts. Вы создали группу составных элементов вашей формы (на данный момент у вас есть один элемент,location). Массив[''] позволяет вам указать некоторые дополнительные параметры для входных данных вашей формы, такие как: предварительное заполнение его некоторыми данными и использование валидаторов для проверки вашего ввода. Вам не нужно ничего из этого для этого урока, поэтому вы можете просто оставить его пустым. Вы можете узнать больше о том, что можно передать в свойство элементаhere.

У вас есть еще две вещи, прежде чем ваша форма будет заполнена. Сначала откройте файлweather.component.html. Вам необходимо присвоить форме свойство[formGroup]. Это свойство будет равно переменной, которую вы только что объявили в файлеweather.component.ts:weatherSearchForm. Во-вторых, вы должны привязать ваш элементlocation (объявленный в вашем файлеweather.component.ts) к вашему HTML. Вweather.component.html добавьте следующее выделенное содержимое:

src/app/weather/weather.component.html

...
formControlName="location" />
...

Вы добавили свойство[formGroup], связывающее вашу форму с HTML. Вы также добавили свойствоformControlName, которое объявляет, что этот конкретный элементinput привязан к элементуlocation в вашем файлеweather.component.ts.

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

Затем вы подключите кнопку, чтобы иметь возможность принимать входные данные в форму.

[[step-7 -—- connected-your-button]] == Шаг 7. Подключение кнопки

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

Если вы посмотрите на свой код вweather.component.html, вы увидите, что ваша кнопка имеет типsubmit:

src/app/weather/weather.component.html

...

Это стандартное значение HTML, которое отправит значения вашей формы какой-либо функции для выполнения действий.

В Angular вы указываете эту функцию в событии(ngSubmit). Когда вы нажимаете кнопку в форме, если она имеет типsubmit, она запускает событие(ngSubmit), которое впоследствии будет вызывать любой назначенный вами метод. В этом случае вы хотите иметь возможность получить местоположение, которое набрал ваш пользователь, и отправить его в API APIXU.

Вы собираетесь сначала создать метод для обработки этого. В вашемweather.component.ts создайте методsendToAPIXU(), который будет принимать один аргумент: значения, которые вы ввели в форму. Добавьте следующий выделенный контент в файл:

src/app/weather/weather.component.ts

...
ngOnInit() {
    this.weatherSearchForm = this.formBuilder.group({
      location: [""]
    });
  }

sendToAPIXU(formValues) {

}
...

Затем добавьте событиеngSubmit в свой HTML и передайте значения отправленной формы в методsendToAPIXU():

weather.component.html

...
...
...

Вы добавили событиеngSubmit в свою форму, подключили свой метод, который хотите запускать при отправке формы, и передали значения вашегоweatherSearchForm в качестве аргумента вашему методу обработчика (weatherSearchForm.valueс). Теперь вы можете проверить, что это работает, используяconsole.log для распечатки вашегоformValues, в методеsendToAPIXU() добавьте следующий выделенный контент вweather.component.ts:

weather.component.ts

...
sendToAPIXU(formValues){
    console.log(formValues);
}

Зайдите в браузер и откройте консоль, щелкнув правой кнопкой мыши в любом месте страницы вашего веб-сайта, а затем нажмитеInspect Element. В открывшемся окне появится вкладка с именемConsole. ВведитеLondon в форму. Когда вы нажмете кнопкуSearch for Weather, вы увидите объект, в котором указано ваше местоположение.

Output from console after updating the sendToAPIXU method

Ваш вывод из консоли - это объект JSON{location: "London"}. Если вы хотите получить доступ к своему значению местоположения, вы можете сделать это, открывformValues.location. Точно так же, если у вас были какие-либо другие входы внутри вашей формы, вы бы заменили.location на любые другие имена элементов, которые у вас были.

[.note] #Note:
Все значения реактивной формы хранятся в объекте - где ключ - это имя значения, которое вы передали вformBuilder.group({}).
#

Кнопка теперь подключена и может правильно принимать ввод. Затем вы заставите методsendToAPIXU() отправлять HTTP-запрос к APIXU API.

[[step-8 -—- call-the-apixu-api]] == Шаг 8. Вызов API APIXU

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

Чтобы выполнять HTTP-запросы в Angular, вам необходимо импортироватьHttpClientModule. Откройте вашsrc/app/app.module.ts и добавьте следующие выделенные строки:

src/app/app.module.ts

...
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
    ...
    imports: [
        BrowserModule,
        RouterModule.forRoot(allAppRoutes),
        ReactiveFormsModule,
        HttpClientModule
    ]
    ...
})
...

Затем вам нужно написать код, чтобы сделать HTTP-вызов API APIXU. Лучше всего создать Angularservice для выполнения HTTP-запросов. Разделение проблем является ключевым в любом приложении, которое вы создаете. Служба позволяет вам переместить все эти HTTP-запросы, которые делает ваше приложение, в один файл, который затем можно вызывать внутри любого файла.component.ts, который вы создаете. Вы можете «легально» записать эти HTTP-запросы в конкретный файл.component.ts, но это не лучшая практика. Например, вы можете обнаружить, что некоторые ваши запросы являются сложными и требуют от вас выполнения некоторых действий постобработки после получения ваших данных. Несколько различных компонентов в вашем приложении могут использовать некоторые из ваших HTTP-запросов, и вы не хотите писать один и тот же метод несколько раз.

В новом окне терминала или остановив сервер в текущем сеансе терминала, выполните следующую команду, чтобы создать службу с именемapixu:

ng g service apixu

Вы увидите вывод, похожий на следующий:

Outputcreate src/app/apixu.service.spec.ts (328 bytes)
create src/app/apixu.service.ts (134 bytes)
...

Команда создала служебный файл (apixu.service.ts) и тестовый файл (apixu.service.spec.ts).

Теперь вам нужно добавить эту службу в качестве поставщика в файлapp.module.ts. Это делает его доступным для использования внутри вашего приложения. Откройте этот файл и сначала импортируйтеApixuService:

src/app/app.module.ts

...
import { HttpClientModule } "@angular/common/http";
import { ApixuService } from "./apixu.service";
...

Затем добавьте недавно импортированныйApixuService в качестве провайдера в блокproviders:

src/app/app.module.ts file

...
@NgModule({
    ...
    providers: [ApixuService],
    ...
})
...

В Angular, если вы хотите использовать созданную вами службу, вам необходимо указать эту службу в качестве поставщика в вашем файлеmodule.ts. В этом случае вы указали его как поставщика для всего приложения вapp.module.ts.

Наконец, откройте файлsrc/app/apixu.service.ts. Вы увидите шаблонный код того, что вам нужно для создания службы: сначала импорт интерфейсаInjectable из Angular; затем тот факт, что служба должна быть с корневым инжекторомprovidedIn (для всего приложения); а затемdecorating (это фактически означает указание) вашей службы как@Injectable.

src/app/apixu.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class ApixuService {

  constructor() { }
}

Оформление службы как@Injectable позволяет вам внедрить эту службу в конструктор вweather.component.ts, чтобы вы могли использовать ее внутри своего компонента.

Если вы остановили свое приложение, перезапустите его, выполнив:

ng serve --o

Как упоминалось выше, ваша служба должна выполнять HTTP-запросы к APIXU API и импортироватьHttpClientModule в файлapp.module.ts, чтобы выполнять HTTP-запросы во всем приложении. Кроме того, вам необходимо импортировать библиотекуHttpClient в файлapixu.service.ts, чтобы выполнять HTTP-запросы к API APIXU из самого файлаapixu.service.ts. Откройте файлapixu.service.ts и добавьте следующее выделенное содержимое:

src/app/apixu.service.ts

...
import { HttpClient } from '@angular/common/http';
...

Теперь вам нужно написать методgetWeather(), который принимает один параметр: местоположение. Этот метод сделает запрос API к APIXU и вернет полученные данные о местоположении.

Для этого вам понадобится предоставленный ключ API при регистрации в API APIXU. Если вы войдете вAPIXU, вы попадете в панель управления:

APIXU Dashboard

Вы увидите свой ключ, а под ним ссылки на URL-адрес API с уже предварительно заполненным ключом дляCurrent Weather иForecast Weather. Скопируйте ссылку HTTPS для получения сведений оCurrent Weather, она будет примерно такой:

https://api.apixu.com/v1/current.json?key=YOUR_API_KEY&q=Paris

Этот URL даст вам текущую информацию о погоде для Парижа. Вместо этого вы хотите иметь возможность передаватьlocation из вашей формы в параметр&q=. Поэтому удалитеParis из URL-адреса, когда вы добавляете его в свой файлapixu.service.ts:

src/app/apixu.service.ts

...
export class ApixuService {

  constructor(private http: HttpClient) {}

  getWeather(location){
      return this.http.get(
          'https://api.apixu.com/v1/current.json?key=YOUR_API_KEY&q=' + location
      );
  }
}

[.note] #Note: Вы использовали ключ API непосредственно в коде. В производственной ситуации вы должны безопасно хранить этот ключ на стороне сервера, извлекать этот ключ безопасным способом и использовать его в своем приложении. Вы можете либо безопасно хранить его на стороне сервера, либо использовать приложение для управления ключами, такое какHashicorp Vault илиAzure Key Vault, чтобы назвать несколько.
#

Вы импортировали и внедрилиHttpClientв конструктор, чтобы его можно было использовать. Вы также создали методgetWeather(), который принимает параметрlocation и отправляет запросGET на указанный вами URL. Вы оставили параметр&q= пустым, так как вы собираетесь указать это местоположение непосредственно из параметраlocation в методе. Наконец, вы вернули данные обратно тому, кто вызвал метод.

Ваш сервис завершен. Вам нужно импортировать свою службу в вашWeatherComponent, вставить ее в свой конструктор, чтобы использовать ее, а затем обновить свой методsendToAPIXU(), чтобы отправить ваше местоположение в вашу недавно созданную службу. Откройте файлweather.component.ts, чтобы выполнить эти задачи, добавив выделенное содержимое:

src/app/weather.component.ts

...
import { FormBuilder, FormGroup } from "@angular/forms";
import { ApixuService } from "../apixu.service";
...
constructor(
    private formBuilder: FormBuilder,
    private apixuService: ApixuService
  ) {}
...
ngOnInit(){...}
sendToAPIXU(formValues){
    this.apixuService
      .getWeather(formValues.location)
      .subscribe(data => console.log(data));
}

Вы удалили бывший операторconsole.log в методеsendToAPIXU() и обновили его этим содержанием. Теперь вы передаете свое местоположение из формы в методsendToAPIXU(), который вы создали ранее. Затем вы передали эти данные методуgetWeather() объектаApixuService, который впоследствии отправил HTTP-запрос к API с этим расположением. Затем вы подписались на полученный ответ и в этом примере записали эти данные на консоль. Вы всегда должны вызывать метод подписки для HTTP-запроса, поскольку запрос не начнется, пока у вас не будет способа прочитать ответObservable, который вы получите. Observables - это способ отправки сообщений между издателями и подписчиками, позволяющий передавать любые данные туда и обратно. Вы не сможете получать данные от наблюдаемой, пока подписчик не подпишется на нее, потому что она не будет выполняться до этого момента.

Снова откройте консоль в вашем браузере. Теперь введитеLondon, UK и щелкнитеSearch for Weather. Если вы нажмете на стрелки вкладки, вы увидите список сведений о погоде в консоли.

Console output from looking for current weather in London

Выходные данные показывают объекты JSON, содержащие всю необходимую информацию о погоде. У вас есть два возвращенных объекта: объектcurrent и объектlocation. Первый дает желаемую информацию о погоде, а второй - о вашем местонахождении.

Теперь вы успешно получили данные о погоде в консоли. Чтобы закончить этот урок, вы отобразите эту информацию о погоде в своем HTML.

[[step-9 -—- displaying-your-weather-data-in-your-app]] == Шаг 9. Отображение данных о погоде в вашем приложении

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

Интерполяция позволяет отображать данные в ваших представлениях. Для этого вам необходимо привязать свойство через стиль{{ }}, чтобы отобразить это свойство в вашем HTML.

Откройте файлweather.component.ts и создайте переменную с именемweatherData, которой вы назначите данные JSON, полученные из API. Кроме того, удалите код, который ранее был в скобках.subscribe(), и замените его следующим выделенным кодом:

src/app/weather/weather.component.ts

...
export class WeatherComponent implements OnInit {
public weatherSearchForm: FormGroup;
public weatherData: any;
...
sendToAPIXU(formValues){
    this.apixuService
    .getWeather(formValues.location)
    .subscribe(data => this.weatherData = data)
      console.log(this.weatherData);
    }
}

Вы создали переменнуюweatherData и заявили, что она может содержать данные типаany. Затем вы присваиваете этой переменной данные, полученные вами от вызова API. Наконец, вы добавили операторconsole.log(), чтобы дважды проверить, чтоweatherData содержит всю полученную вами информацию.

На этом этапе ваш файлweather.component.ts должен выглядеть так:

src/app/weather/weather.component.ts

import { Component, OnInit } from "@angular/core";
import { FormBuilder, FormGroup } from "@angular/forms";
import { ApixuService } from "../apixu.service";

@Component({
  selector: "app-weather",
  templateUrl: "./weather.component.html",
  styleUrls: ["./weather.component.css"]
})
export class WeatherComponent implements OnInit {
  public weatherSearchForm: FormGroup;
  public weatherData: any;

  constructor(
    private formBuilder: FormBuilder,
    private apixuService: ApixuService
  ) {}

  ngOnInit() {
    this.weatherSearchForm = this.formBuilder.group({
      location: [""]
    });
  }

  sendToAPIXU(formValues) {
    this.apixuService.getWeather(formValues.location).subscribe(data => {
      this.weatherData = data;
      console.log(this.weatherData);
    });
  }
}

Если вы вернетесь и снова выполните поискLondon, UK, вы увидите, что ваш объект распечатан на консоли как обычно. Теперь вы хотите показать эти данные в своем HTML. Если вы изучите объектcurrent из полученных данных о погоде в консоли, вы увидите такие значения, какcondition,feelslike_c,feelslike_f,temp_c, temp_f и т. д. Вы собираетесь использовать все пять из этих свойств.

Снова откройте файлweather.component.html и добавьте субтитры к данным, которые вы хотите отобразить. Вы добавите эти теги<p> во второйcol-md-6:

src/app/weather/weather.component.html

...

Weather Details:

Current weather conditions:

Temperature in Degrees Celsius:

Temperature in Degrees Farenheit:

Feels like in Degrees Celsius:

Feels like in Degrees Farenheit:

Location Searched:

Затем вы добавите данные, полученные от объекта JSON, в свой HTML-код:

weather.component.html

...

Weather Details:

Current weather conditions: {{this.weatherData?.current.condition.text}}

Temperature in Degrees Celsius: {{this.weatherData?.current.temp_c}}

Temperature in Degrees Farenheit: {{this.weatherData?.current.temp_f}}

Feels like in Degrees Celsius: {{this.weatherData?.current.feelslike_c}}

Feels like in Degrees Farenheit: {{this.weatherData?.current.feelslike_f}}

Location Searched: {{this.weatherData?.location.name}}, {{this.weatherData?.location.country}}

Вы использовали оператор? при получении данных из переменнойweatherData в вашем HTML. Этот оператор называетсяElvis Operator.

Поскольку вы выполняете HTTP-вызов, вы отправляете запросasynchronous. Вы получите эти данные в какой-то момент, но это не будет немедленным ответом. Angular, однако, по-прежнему будет заполнять ваш HTML данными, указанными вами в переменнойweatherData. Если вы не получили данные обратно к тому времени, когда Angular начнет заполнять ваши абзацы, возникнет ошибка, сообщающая, что Angular не может найти эти данные. Например,.current или.location будет отображаться как undefined.

Оператор Элвиса -safe navigator и предотвращает это. Он сообщает Angular подождать и проверить, определен лиweatherData первым, прежде чем продолжить и показать эти данные в HTML. Как толькоweatherData получит всю свою информацию, Angular обновит ваши привязки и покажет ваши данные как обычно.

Итоговый файлweather.component.ts будет выглядеть следующим образом:

weather.component.html

Search for Weather:

Weather Details:

Current weather conditions: {{ this.weatherData?.current.condition.text }}.

Temperature in Degrees Celsius: {{ this.weatherData?.current.temp_c }}

Temperature in Degrees Farenheit: {{ this.weatherData?.current.temp_f }}

Feels like in Degrees Celsius: {{ this.weatherData?.current.feelslike_c }}

Feels like in Degrees Farenheit: {{ this.weatherData?.current.feelslike_f }}

Location Searched: {{ this.weatherData?.location.name }}, {{ this.weatherData?.location.country }}.

Вы использовали шаблон возвращенного погодного объекта JSON, чтобы вывести нужные данные. Сохраните файл, вернитесь в браузер и введитеLondon, UK, вы увидите, что ваши данные о погоде появятся справа.

Finished app showing weather data from London

Попробуйте использовать его в разных местах, например:San Francisco, US,Dakar, Senegal иHonololu, Hawaii. Вы увидите соответствующие данные о погоде для всех этих мест.

Заключение

Вы создали приложение погоды с помощью Angular, Bootstrap и API APIXU. Вы создали проект Angular с нуля, следуя передовым методикам Angular, и в то же время убедитесь, что ваше приложение хорошо спроектировано и настроено надлежащим образом.

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

Еще одна возможность, которую следует рассмотреть для добавления в ваше приложение, - этоhandling errors из ваших HTTP-запросов; например, если вы ввели неверное местоположение. Еще одним улучшением будет отображение разных изображений, если температура находится между определенными пороговыми значениями. Вы также можете создавать различные приложения с Angular, используя другие API.

Вы также можете использоватьNgBootstrap, это специальный тип Bootstrap, созданный для Angular. Это позволяет использовать все стандартные виджеты Bootstrap JavaScript, а также некоторые специальные, не включенные в стандартную установку, специально адаптированные для Angular.

Полный код этого руководства доступен наGitHub.

Related