Итак, в предыдущих разделах мы подготовили проект к практической работе. В данном разделе мы рассмотрим, что такое привязка данных («байндинг», от англ. binding — связывание) в Angular и как ее делать.
Привязки используются для передачи каких-либо данных из компонента в шаблон и обратно. Есть несколько типов привязок в Angular:
- Строчная интерполяция — привязка содержимого html-элемента к значению переменной из компонента. Выглядит следующим образом {{ value }}. Это односторонняя привязка, используется для того, чтобы передать переменную в компонент Angular.
- Привязка свойств (атрибутов) html-элемента. Например,
<input type="text" [value]="input.value">
В данном примере в атрибут value будет занесено значение свойства value объекта input, манипуляции над которым будут производиться в компоненте. - Привязка событий — это привязка метода определенного в компоненте к событию DOM, например к клику
<button (click)="changeData(title, price)">Изменить</button>
В этом случае при клике на кнопку будет срабатывать метод changeData() с переданными ему параметрами title и price - Также существует двусторонняя привязка. Она используется в элементах форм.
<input [(ngModel)]="title">
В таком случае изменение значения в компоненте приводит к моментальному изменению значения в шаблоне, и наоборот, если к примеру сделать это к текстовому полю шаблона, то как только будет введено какое-либо значение, оно сразу будет передаваться в компонент.
Строчная интерполяция
Протестируем первый вид привязки. Изменим код шаблона, а именно его заголовок:
<div class="container">
<div class="row">
<h3>{{ title }}</h3>
<table class="table table-striped text-center">
<thead class="thead-dark">
Затем изменим файл компонента и добавим переменную title
import { Component, OnInit } from '@angular/core';
import { DataService } from '../shared/data.service';
@Component({
selector: 'app-all-products',
templateUrl: './all-products.component.html',
styleUrls: ['./all-products.component.css']
})
export class AllProductsComponent implements OnInit {
title = 'Каталог товаров';
products = [];
constructor(private dataService: DataService) { }
ngOnInit() {
this.products = this.dataService.products;
}
}
Теперь при изменении значения переменной title в компоненте, изменения также мгновенно будут отображаться в шаблоне. Попробуйте задать разные значения для переменной title и проверьте результат.
Также в такой привязке можно передавать не только переменную, а и, скажем, функцию, которая будет возвращать какое-то значение, или просто выполнять арифметические операции.
Привязка свойств и событий
Теперь сделаем второй и третий тип привязки. Добавим в разметку следующий элемент:
<div class="container">
<div class="row">
<h3 class="mr-3 mt-2">{{ title }}</h3>
<div class="form-inline">
<input type="checkbox" class="mr-2"
[checked]="isChecked"
(click)="changeIsChecked()">
<input type="text" class="form-control mr-3"
[value]="title"
[disabled]="isChecked">
<button class="btn btn-primary"
[disabled]="isChecked"
(click)="editTitle()">Изменить</button>
</div> <!-- /form-inline -->
.....
Для большей наглядности привязки перенесены на новую строку.
В файле компонента сделаем следующие изменения:
...
export class AllProductsComponent implements OnInit {
title = 'Каталог товаров';
isChecked: boolean = true;
products = [];
constructor(private dataService: DataService) { }
ngOnInit() {
this.products = this.dataService.products;
}
changeIsChecked() {
this.isChecked = !this.isChecked;
}
editTitle() {
this.title = 'Новый тайтл';
}
}
Теперь рассмотрим, что мы изменили.
В разметке первому input с типом checkbox мы сделали привязку к атрибуту checked и сразу же к событию click привязали выполнение метода changeIsChecked, который просто будет менять флаг isChecked на противоположное значение. По умолчанию isChecked = true, при клике на чекбоксе сработает метод changeIsChecked и сменит значение на false, при втором клике снова поменяет его на true.
Следующий input с типом text и кнопка также зависят от значения флага isChecked — если чекбокс отмечен (т.е. isChecked = true), тогда срабатывает привязка к атрибуту disabled и эти элементы отключаются. Как только вы снимите чекбокс, они станут доступны. Также к текстовому полю, к атрибуту есть привязка переменной с заголовком [value]='title'
Еще одна привязка в этом примере сделана к кнопке — при клике на кнопку срабатывает метод changeTitle() и наш заголовок меняется на ‘Новый тайтл’.
Таким же способом можно сделать и привязку к атрибуту [class] или [style] любого тега
[class]="выражение"— данная привязка заменит все классы заданные элементу[class.className]="выражение"— добавляет указанный класс, можно в качестве выражения добавить функцию[style.myStyle]="выражение"— придает css-свойству myStyle результат выполнения выражения, напримерbackgroundColor(записывается именно в ‘кэмэл кейсе’, без дефиса). Нужно также указывать единицы измерения (например, px —[style.fontSize]="14px")[style.myStyle.units]="выражение"— идентичная привязка, только тут можно указать единицы измерения в цели, а не в выражении. Например,[style.fontSize.px]="14"
Но для этих целей чаще всего используются директивы [ngClass] и [ngStyle], которые мы рассмотрим в следующей главе.
Двусторонняя привязка
А теперь давайте сделаем двухстороннюю привязку и будем менять заголовок на то значение, которое будем вводить в поле input.
Давайте для начала подготовим наш проект. В файле шаблона компонента нужно заменить эти строки, вместо [value] вставляем директиву [(ngModel)]
...
<input type="text" class="form-control mr-3"
[(ngModel)]="title"
[disabled]="isChecked">
...
Далее в файле app.module.ts нам обязательно нужно подключить FormsModule
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { AllProductsComponent } from './all-products/all-products.component';
import { DataService } from './shared/data.service'
@NgModule({
declarations: [
AppComponent,
AllProductsComponent
],
imports: [
BrowserModule,
FormsModule
],
providers: [DataService],
bootstrap: [AppComponent]
})
export class AppModule { }
Теперь как только вы вводите значение в поле input, у вас сразу же моментально меняется заголовок. И наоборот — если изменить значение переменной title в файле компонента, то оно будет обновлено и в шаблоне. Этого же эффекта можно было бы добиться без двухсторонней привязки, но в таком случае нам нужно было бы отлавливать событие (input) и уже в зависимости от введенного значения, менять атрибут [value]. Директива [(ngModel)] упрощает работу с привязками.
Итак, вкратце:
[атрибут/свойство]="выражение" — односторонняя привязка, данные передаются от выражения к цели (применяется для свойств и атрибутов){{ выражение }} — привязка со строковой интерполяцией(событие)="выражение" — круглые скобки обозначают одностороннюю привязку к событию[(ngModel)]="выражение" — двусторонняя привязка
Добавить комментарий