3. «Редактор Героев» – Angular 6

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

Используя CLI запустим команду:

ng generate component heroes

CLI создаст новую папку  src/app/heroes/ и сгенерирует 3 файла HeroesComponent.

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

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

Мы всегда импортируем Component из библиотеки agngular/core и декорируем класс с помощью @Component.

@Component – функция декоратока которая определяет метаданные компонента в Angular.

CLI сгенерировале три свойства метаданных:

  • selector – CSS селектор компонента
  • templateUrl – путь к шаблону компонента
  • styleUrls – путь к файлу стилей компонента

СSS-селектор ‘app-heroes’, также соответствует имени элемента HTML, который идентифицирует этот компонент в шаблоне родительского компонента.

Метод ngOnInit – хук жизненного цикла компонента.  Angular вызывает ngOnInit незамедлительно после создания компонента. Хорошее место для описания логики инициализации.

Всегда экспортируйте класс компонента, чтобы вы могли импортировать его в дрогом месте, например, AppModule.

Дальше, добавим свойство hero в HeroesComponent для героя, например, Windstorm.

hero = 'Windstorm';

Для отображения имени героя откроем файл шаблона heroes.component.html. Удалим из него все и запишем одну строку

{{ hero }}

– которая будет выводить имя нашего героя.

Отобразим наш компонент на экран. Для этого нам нужно добавить HeroesComponent в AppComponent.

Запомним, что app-heroes – селектор компонента HeroesComponent.

Поэтому добавим элемент <app-heroes> в файл шаблона AppComponent, чуть ниже названия.

<h1>{{title}}</h1>
<app-heroes></app-heroes>

Предполагая, что команда CLI ng serve все еще запущена, браузер должен обновить и отобразить как заголовок приложения, так и имя героя.

Модель Героя

Настоящий герой – не просто имя.

Создайте класс Hero в своем файле в папке src/app. Дайте ему свойства id и name.

export class Hero {
  id: number;
  name: string;
}

Вернемся в HeroesComponent и импортируем туда модель Hero и немного отрефакторим наш код, изменив тип свойства hero со string на Hero и сразу же его инициализируем { id: 1, name: ‘Windstorm’ }.

import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  hero: Hero = {
    id: 1,
    name: 'Windstorm'
  };

  constructor() { }

  ngOnInit() {
  }

}

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

Отобразим объект angular на экран

<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div><span>name: </span>{{hero.name}}</div>

Браузер перезагрузиться и отобразит желаемую информацию.

Отформатируем текст с помощью UppercasePipe

<h2>{{hero.name | uppercase}} Details</h2>

После обновления, увидим что имя героя отображается заглавными буквами. Слово uppercase в интерполяции сразу после оператора | активирует встроенный в Angular UppercasePipe.

Pipes – способ форматирования строк, сумм валют, дат и других отображаемых данных. Angular поставляеться с несколькими встроенными пайпами, а также, мы можем создавать свои собственные.

Редактор героев

Пользователи должны иметь возможность редактировать имя героя в текстовом поле <input>.

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

Чтобы автоматизировать этот поток, настроим двустороннюю привязку (two-way data binding) между элементом формы <input> и свойством hero.name.

Двусторонее связывание

Обновим шаблон HeroesComponent

<div>
  <label>name:
    <input [(ngModel)]="hero.name" placeholder="name">
  </label>
</div>

[(ngModel)] – синтаксис двустороннего связывания данных в Angular.

Здесь мы связвываем свойство hero.name с текстовым полем HTML, чтобы данные могли поступать в обоих направлениях: от свойства hero.name до текстового поля и от текстового поля обратно к имени hero.name.

Обратите внимание, что приложение перестало работать, когда вы добавили [(ngModel)].

Чтобы увидеть эту ошибку, откройте средства разработки браузера и загляните в консоль для сообщения типа

Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'.

Хотя ngModel является действующей директивой Angular, по умолчанию она недоступена.

Она принадлежит к дополнительному модулю FormsModule, и вы должны его использовать.

AppModule

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

Некоторые метаданные находятся в декораторах @Component, добавленных в классы компонентов. Другие критические метаданные находятся в декораторах @NgModule.

Самый важный декоратор @NgModule аннотирует класс AppModule верхнего уровня.

Angular CLI сгенерировал класс AppModule в src/app/app.module.ts, когда был создан проект. Сюда же мы и добавим наш FormsModule.

import { FormsModule } from '@angular/forms'; // <-- NgModel lives here
imports: [
  BrowserModule,
  FormsModule
],

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

import { HeroesComponent } from './heroes/heroes.component';
declarations: [
  AppComponent,
  HeroesComponent
],

Когда браузер обновится, приложение должно снова работать. Вы можете отредактировать имя героя и увидеть изменения, отраженные сразу в <h2> над текстовым полем.

Code review

import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  hero: Hero = {
    id: 1,
    name: 'Windstorm'
  };

  constructor() { }

  ngOnInit() {
  }

}
<h2>{{hero.name | uppercase}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
  <label>name:
    <input [(ngModel)]="hero.name" placeholder="name">
  </label>
</div>
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here

import { AppComponent } from './app.component';
import { HeroesComponent } from './heroes/heroes.component';

@NgModule({
  declarations: [
    AppComponent,
    HeroesComponent
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Tour of Heroes';
}
<h1>{{title}}</h1>
<app-heroes></app-heroes>
export class Hero {
  id: number;
  name: string;
}

Итоги

  • Использовали консоль для создания второго компонента
  • Вывели компонент на екран
  • Использовали форматирование текста при помощи UppercasePipe
  • Научились использовать дву-стороннее связывание данных при помощи ngModel
  • Немного затронули AppModule
  • Импортировали необходимые зависимости для работы нашего приложения

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.