Как я могу выбрать элемент в шаблоне компонента?
кто-нибудь знает, как получить элемент, определенный в шаблоне компонента? Полимер делает его очень легко с $ и $$.
мне просто интересно, как это сделать в Angular.
возьмите пример из учебника:
import {Component} from '@angular/core'
@Component({
selector:'display'
template:`
<input #myname(input)="updateName(myname.value)"/>
<p>My name : {{myName}}</p>
`
})
export class DisplayComponent {
myName: string = "Aman";
updateName(input: String) {
this.myName = input;
}
}
как мне ухватиться за ссылку p или input элемент из определения класса?
10 ответов:
вместо введения
ElementRefи с помощьюquerySelectorили аналогичного оттуда, декларативный способ может быть использован вместо того, чтобы получить доступ к элементам в представлении напрямую:<input #myname>@ViewChild('myname') input;элемент
ngAfterViewInit() { console.log(this.input.nativeElement.value); }
- @ViewChild() поддерживает директиву или тип компонента в качестве параметра, или имя (строка) переменной шаблона.
- @ViewChildren() также поддерживает список имен, разделенных запятыми (в настоящее время пробелы не допускаются
@ViewChildren('var1,var2,var3')).- @ContentChild() и @ContentChildren() сделайте то же самое, но в свете DOM (
<ng-content>проектируемых элементов).потомки
@ContentChildren()это единственный, который позволяет также запрашивать потомков@ContentChildren(SomeTypeOrVarName, {descendants: true}) someField;
{descendants: true}должно быть по умолчанию, но не в 2.0.0 final и это считается ошибка
Это было исправлено в 2.0.1читать
если есть компонент и директивы
ViewContainerRefэто требуется для динамически создаваемых компонентов, а не по умолчаниюElementRef@ViewChild('myname', { read: ViewContainerRef }) target;подписаться на изменения
хотя просмотр детей задается только тогда, когда
ngAfterViewInit()вызывается и содержание детей устанавливаются только тогда, когдаngAfterContentInit()называется, если вы хотите подписаться на изменения результата запроса, это должно быть сделано вngOnInit()https://github.com/angular/angular/issues/9689#issuecomment-229247134
@ViewChildren(SomeType) viewChildren; @ContentChildren(SomeType) contentChildren; ngOnInit() { this.viewChildren.changes.subscribe(changes => console.log(changes)); this.contentChildren.changes.subscribe(changes => console.log(changes)); }direct DOM доступ
может запрашивать только элементы DOM, но не компоненты или экземпляры директив:
export class MyComponent { constructor(private elRef:ElementRef) {} ngAfterViewInit() { var div = this.elRef.nativeElement.querySelector('div'); console.log(div); } // for transcluded content ngAfterContentInit() { var div = this.elRef.nativeElement.querySelector('div'); console.log(div); } }получить произвольное проецируемое содержимое
посмотреть доступ к транскрипции контента
вы можете получить дескриптор элемента DOM через
ElementRefпутем введения его в конструктор вашего компонента:constructor(myElement: ElementRef) { ... }Docs:https://angular.io/docs/ts/latest/api/core/index/ElementRef-class.html
import { Component, ElementRef, OnInit } from '@angular/core'; @Component({ selector:'display', template:` <input (input)="updateName($event.target.value)"> <p> My name : {{ myName }}</p> ` }) class DisplayComponent implements OnInit { constructor(public element: ElementRef) { this.element.nativeElement // <- your direct element reference } ngOnInit() { var el = this.element.nativeElement; console.log(el); } updateName(value) { // ... } }пример обновлен для работы с последней версией
для получения более подробной информации о родную стихию, здесь
угловые 4+: Используйте
renderer.selectRootElementс селектором CSS для доступа к элементу.у меня есть форма, которая изначально отображает ввод электронной почты. После ввода сообщения электронной почты форма будет расширена, чтобы они могли продолжать добавлять информацию, касающуюся их проекта. Однако, если они не существующий клиент, форма будет включать в себя раздел Адреса над разделом информации о проекте.
на данный момент часть ввода данных не была разбиты на компоненты, поэтому разделы управляются с помощью директив *ngIf. Мне нужно установить фокус на поле примечания к проекту, если они являются существующим клиентом, или поле имени, если они новые.
Я пробовал решения без успеха. Тем не менее, обновление 3 в этой ответ дал мне половину возможного решения. Другая половина исходила от ответа Маттеони в этой нить. В результате получается следующее:
import { NgZone, Renderer } from '@angular/core'; constructor(private ngZone: NgZone, private renderer: Renderer) {} setFocus(selector: string): void { this.ngZone.runOutsideAngular(() => { setTimeout(() => { this.renderer.selectRootElement(selector).focus(); }, 0); }); } submitEmail(email: string): void { // Verify existence of customer ... if (this.newCustomer) { this.setFocus('#firstname'); } else { this.setFocus('#description'); } }Так как единственное, что я выполнение-это установка фокуса на элементе, мне не нужно беспокоиться об обнаружении изменений, поэтому я могу фактически запустить вызов
renderer.selectRootElementвнешний угловой. Поскольку мне нужно дать новым разделам время для рендеринга, раздел элемента обернут в тайм-аут, чтобы позволить потокам рендеринга догнать время до попытки выбора элемента. После того, как все это настроено, я могу просто вызвать элемент с помощью базовых селекторов CSS.Я знаю, что этот пример касался в первую очередь фокуса событие, но мне трудно, что это не может быть использовано в других контекстах.
для людей, пытающихся захватить экземпляр компонента внутри
*ngIfили*ngSwitchCase, вы можете следовать этому трюку.создать
импортируйте декоратор ViewChild из @angular / core, например:
<form #f="ngForm"> ... </form> import { ViewChild } from '@angular/core'; class TemplateFormComponent { @ViewChild('f') myForm: any; . . . }теперь вы можете использовать объект 'myForm' для доступа к любому элементу в нем в классе.
источник: https://codecraft.tv/courses/angular/forms/template-driven/
*/ import {Component,ViewChild} from '@angular/core' /*Import View Child*/ @Component({ selector:'display' template:` <input #myname (input) = "updateName(myname.value)"/> <p> My name : {{myName}}</p> ` }) export class DisplayComponent{ @ViewChild('myname')inputTxt:ElementRef; /*create a view child*/ myName: string; updateName: Function; constructor(){ this.myName = "Aman"; this.updateName = function(input: String){ this.inputTxt.nativeElement.value=this.myName; /*assign to it the value*/ }; } }
Я хотел бы добавить, что если вы используете
ElementRef, Как рекомендуется всеми ответами, то вы сразу же столкнетесь с проблемой, чтоElementRefимеет ужасное объявление типа, которое выглядит какexport declare class ElementRef { nativeElement: any; }это глупо в среде браузера, где nativeElement является
HTMLElement.чтобы обойти это, вы можете использовать следующую технику
import {Inject, ElementRef as ErrorProneElementRef} from '@angular/core'; interface ElementRef { nativeElement: HTMLElement; } @Component({...}) export class MyComponent { constructor(@Inject(ErrorProneElementRef) readonly elementRef: ElementRef) { } }
чтобы получить непосредственного следующего брата, используйте это
event.source._elementRef.nativeElement.nextElementSibling
выбор элемента из списка. Легко выбрать определенный элемент из списка одинаковых элементов.
компонент код:
export class AppComponent { title = 'app'; listEvents = [ {'name':'item1', 'class': ''}, {'name':'item2', 'class': ''}, {'name':'item3', 'class': ''}, {'name':'item4', 'class': ''} ]; selectElement(item: string, value: number) { console.log("item="+item+" value="+value); if(this.listEvents[value].class == "") { this.listEvents[value].class='selected'; } else { this.listEvents[value].class= ''; } } }HTML-код:
<ul *ngFor="let event of listEvents; let i = index"> <li (click)="selectElement(event.name, i)" [class]="event.class"> {{ event.name }} </li>css код:
.selected { color: red; background:blue; }
Comments