angular создать Как выбрать элемент в шаблоне компонента?




создать компонент angular (8)

Я хотел бы добавить, что если вы используете 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) { }
}

Кто-нибудь знает, как получить элемент, определенный в шаблоне компонента? Полимер делает это очень легко с $ и $$ .

Мне просто интересно, как это сделать в 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 из определения класса?


Угловое 4+ : Используйте renderer.selectRootElement с помощью селектора CSS для доступа к элементу.

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

На данный момент часть ввода данных не была разбита на компоненты, поэтому секции управляются с помощью директив * ngIf. Мне нужно установить фокус на поле проектных заметок, если они являются существующим клиентом, или поле имени, если они новы.

Я пробовал решения без успеха. Однако обновление 3 в this ответе дало мне половину возможного решения. Другая половина была получена от ответа MatteoNY в this теме. В результате получается следующее:

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 вне Angular. Поскольку мне нужно предоставить время для рендеринга новых секций, секция элемента завершается в тайм-аут, чтобы разрешить время потоков рендеринга до того, как будет предпринята попытка выбора элемента. После того, как все это будет установлено, я могу просто вызвать элемент с помощью основных селекторов CSS.

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


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) {
    // ...
  }
}

Пример обновлен для работы с последней версией

Для получения дополнительной информации о родном элементе here


импортируйте декоратор 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/


Вместо того, чтобы вводить ElementRef и использовать querySelector или аналогичный оттуда, вместо этого можно использовать декларативный способ для прямого доступа к элементам в представлении:

<input #myname>
@ViewChild('myname') input; 

элемент

ngAfterViewInit() {
  console.log(this.input.nativeElement.value);
}

Пример StackBlitz

  • @ViewChild() поддерживает директиву или тип компонента как параметр или имя (строку) переменной шаблона.
  • @ViewChildren() также поддерживает список имен как список, разделенный запятыми (в настоящее время пробелы не разрешены @ViewChildren('var1,var2,var3') ).
  • @ContentChild() и @ContentChildren() делают то же самое, но в свете DOM ( <ng-content> проецируемых элементов).

потомки

@ContentChildren() - единственный, который позволяет также запрашивать потомков

@ContentChildren(SomeTypeOrVarName, {descendants: true}) someField; 

{descendants: true} должны быть по умолчанию, но не в версии 2.0.0, и это считается ошибкой
Это было исправлено в 2.0.1

читать

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

Например 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));
}

прямой доступ 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);
  }
}

получить произвольный прогнозируемый контент

См. Доступ к удаленному контенту


чтобы получить ближайшего следующего брата, используйте это

event.source._elementRef.nativeElement.nextElementSibling


Для людей, пытающихся захватить экземпляр компонента внутри *ngIf или *ngSwitchCase , вы можете следовать этому трюку.

Создайте директиву init .

import {
    Directive,
    EventEmitter,
    Output,
    OnInit,
    ElementRef
} from '@angular/core';

@Directive({
    selector: '[init]'
})
export class InitDirective implements OnInit {
    constructor(private ref: ElementRef) {}

    @Output() init: EventEmitter<ElementRef> = new EventEmitter<ElementRef>();

    ngOnInit() {
        this.init.emit(this.ref);
    }
}

Экспортируйте свой компонент с таким именем, как myComponent

@Component({
    selector: 'wm-my-component',
    templateUrl: 'my-component.component.html',
    styleUrls: ['my-component.component.css'],
    exportAs: 'myComponent'
})
export class MyComponent { ... }

Используйте этот шаблон, чтобы получить экземпляр ElementRef и MyComponent

<div [ngSwitch]="type">
    <wm-my-component
           #myComponent="myComponent"
           *ngSwitchCase="Type.MyType"
           (init)="init($event, myComponent)">
    </wm-my-component>
</div>

Использовать этот код в TypeScript

init(myComponentRef: ElementRef, myComponent: MyComponent) {
}




angular-components