=====Шаблонные переменные, ViewChild===== Шаблонные переменные позволяют определить некоторые переменные внутри шаблона компонента и затем ссылаться к этим переменным из этого же шаблона. Для определения подобных переменных применяется знак решетки (#). Например, определим шаблонную переменную userName в компоненте: import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: `

{{name}}

{{userName.textContent}}

` }) export class AppComponent { name:string="Tom"; }
Определение переменной выглядит следующим образом:

{{name}}

Определение переменной userName в элементе параграфа означает, что она будет представлять данный параграф, то есть элемент p разметки html. И далее мы можем обращаться к этому параграфу через данную переменную. Например, через свойство //userName.textContent// можно получить текстовое содержимое параграфа. При этом, если привязанное к параграфу значение переменной name изменится, то соответственно изменится и значение //userName.textContent//: {{ :angular:angular2:component:2.14.png |}} При этом данную переменную мы можем использовать только внутри шаблона.\\ \\ Использование шаблонных переменных открывает нам дополнительный способ взаимодействия между родительским и дочерним компонентом. Например, определим следующий дочерний компонент //ChildComponent//: import { Component} from '@angular/core'; @Component({ selector: 'child-comp', template: `

{{counter}}

` }) export class ChildComponent{ counter: number = 0; increment() { this.counter++; } decrement() { this.counter--; } }
В этом компоненте определяется переменная счетчика counter. Для ее увеличения или уменьшения применяются методы increment и decrement.\\ \\ В коде главного компонента будем вызывать дочерний компонент: import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: ` ` }) export class AppComponent { } В данном случае шаблонная переменная counter, определенная внутри тега '''', поэтому она будет представлять компонент //ChildComponent//.\\ \\ Соответственно далее мы можем ссылаться к компоненту ChildComponent через эту переменную, например, установить для событий кнопок привязку к методам ChildComponent. В итоге по нажатию на кнопки в главном компоненте будут вызываться методы из дочернего компонента:\\ {{ :angular:angular2:component:2.15.png |}} \\ ====ViewChild==== Однако шаблонные переменные имеют свои ограничения: они не могут применяться вне шаблона, даже в коде класса компонента. Например, мы **НЕ** можем написать так: import { Component} from '@angular/core'; @Component({ selector: 'my-app', template: ` ` }) export class AppComponent { increment() { this.counter++; } decrement() { this.counter--; } } Здесь для класса AppComponent свойства //this.counter// не существует - оно существует только для шаблона.\\ \\ Чтобы все таки иметь возможность обращаться к методам и прочей функциональности дочернего компонента, надо использовать декоратор **ViewChild**. Данный декоратор применяется к свойству и получает селектор элемента DOM, который необходимо отслеживать. И если отслеживаемый по селектору элемент изменяется, то **ViewChild** изменяет состояние свойства. Так, изменим главный компонент следующим образом: import { Component, ViewChild } from '@angular/core'; import { ChildComponent} from './child.component'; @Component({ selector: 'my-app', template: ` ` }) export class AppComponent { @ViewChild(ChildComponent, {static: false}) private counterComponent: ChildComponent; increment() { this.counterComponent.increment(); } decrement() { this.counterComponent.decrement(); } } Первый параметр декоратора ViewChild указывает на селектор элемента, который будет отслеживаться. В качестве селектора может использоваться класс с декоратором @Component, то есть класс компонента, например, ChildComponent. Второй параметр - static - указывает, как будет производиться отслеживание изменений. ====Привязка ViewChild к шаблонным переменным==== Несмотря на то, что выше мы не использовали переменные, тем не менее с помощью декоратора ViewChild также можно связать свойство и переменную из шаблона. Так, изменим код главного компонента: import { Component, ViewChild, ElementRef } from '@angular/core'; @Component({ selector: 'my-app', template: `

{{name}}

{{nameText.textContent}}

` }) export class AppComponent { @ViewChild("nameText", {static: false}) nameParagraph: ElementRef; name: string = "Tom"; change() { console.log(this.nameParagraph.nativeElement.textContent); this.nameParagraph.nativeElement.textContent = "hell"; } }
Здесь в шаблоне определяется переменная nameText, которая представляет код параграфа. А в декоратор ViewChild передается имя этой переменной. Поэтому свойство nameParagraph, к которому применяется декоратор, будет указывать на эту переменную nameText. Причем свойство nameParagraph представляет тип ElementRef, который используется для ссылки на элементы html.\\ \\ По нажатию на кнопку выводится и изменяется текстовое содержимое этой переменной. ====ContentChild==== Кроме //ViewChild// для связи с шаблонными переменными мы можем применять другой декоратор - **ContentChild**, который работает похожим образом. В какой ситуации он может понадобится? Допустим, в родительском компоненте определен следующий код: import { Component} from '@angular/core'; @Component({ selector: 'my-app', template: `

Добро пожаловать {{name}}!

` }) export class AppComponent { name: string = "Tom"; }
Здесь определена переменная //#headerContent//, которая указывает на элемент заголовка h3.\\ \\ Причем поскольку данные из родительского компонента передаются в дочерний напрямую, то для получения этих данных в дочернем компоненте будет использоваться элемент //ng-content//: import { Component, ContentChild, ElementRef } from '@angular/core'; @Component({ selector: 'child-comp', template: ` ` }) export class ChildComponent{ @ContentChild("headerContent", {static:false}) header: ElementRef; change() { console.log(this.header); this.header.nativeElement.textContent = "Hell to world!"; } } И как раз чтобы получить переменные, которые передаются с кодом через ng-content, дочерний компонент применяет декоратор **ContentChild**. В этот декоратор также передается название переменной. Само свойство декоратора также представляет объект ElementRef. И далее мы можем манипулировать этим объектом.