source

컴포넌트 템플릿에서 요소를 선택하려면 어떻게 해야 합니까?

manycodes 2023. 2. 22. 22:49
반응형

컴포넌트 템플릿에서 요소를 선택하려면 어떻게 해야 합니까?

컴포넌트 템플릿에 정의되어 있는 요소를 입수하는 방법을 알고 있는 사람이 있습니까? 수 .$ ★★★★★★★★★★★★★★★★★」$$.

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클래스 정의 내의 요소

사사 instead instead를 하는 대신」을 삽입한다.ElementRef and and를 합니다.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를 지정할 수 있습니다.parameter는 반환할 인스턴스를 지정합니다.

를 들어, 「」입니다.ViewContainerRef 「Components」가 동적으로 에 의해 됩니다.ElementRef

@ViewChild('myname', { read: ViewContainerRef }) target;

변경 내용을 등록하다

뷰는 다음과 같은 경우에만 설정됩니다.ngAfterViewInit()는 '아이들'이 '아이들'이 '아이들'이 '아이들'이 '아이들'이 될 때만 됩니다.ngAfterContentInit()합니다.결과의 하려면 , 라고 형식으로 해 . 쿼리 결과의 변경에 등록하려면 다음 URL에서 수행해야 합니다.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);
  }
}

임의의 예상 콘텐츠를 취득하다

변환된 콘텐츠 액세스 참조

핸들은 DOM 에서 할 수 .ElementRef컴포넌트의 컨스트럭터에 주입하면 다음과 같이 됩니다.

constructor(private myElement: ElementRef) { ... }

문서: 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.selectRootElementCSS ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」

처음에 이메일 입력을 표시하는 양식을 가지고 있습니다.이메일이 입력되면 양식이 확장되어 프로젝트와 관련된 정보를 계속 추가할 수 있게 됩니다.단, 기존 클라이언트가 아닌 경우 양식에는 프로젝트 정보 섹션 위에 주소 섹션이 포함됩니다.

현시점에서는 데이터 입력 부분은 컴포넌트로 분할되어 있지 않기 때문에 *ngIf 지시로 관리하고 있습니다.기존 클라이언트의 경우 프로젝트 노트 필드에 포커스를 설정하고, 신규 클라이언트의 경우 이름 필드에 포커스를 설정해야 합니다.

나는 그 해결책을 시도해 보았지만 성공하지 못했다.그러나 이 답변의 업데이트 3을 통해 최종 솔루션의 절반을 얻을 수 있었습니다.나머지 반쪽은 마테오에서 왔어요NY의 답변입니다.결과는 다음과 같습니다.

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 셀렉터를 사용하여 요소를 호출할 수 있습니다.

이 예에서 주로 포커스 이벤트를 다룬 것은 알지만, 다른 맥락에서 사용할 수 없다는 것은 어렵습니다.

업데이트: 각도 저하 지원RendererAngular 4는 Angular 9는 Angular 9입니다.은 should should이음 음음음 음음 to로 을 받지 .Renderer2상세한 것에 대하여는, 다음의 링크를 참조해 주세요.렌더러2로의 렌더러 이행

*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 리 and 。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) {
}

ViewChild@angular/core다음과 같이 합니다.

HTML 코드:

<form #f="ngForm"> 
  ... 
  ... 
</form>

TS 코드:

import { ViewChild } from '@angular/core';

class TemplateFormComponent {

  @ViewChild('f') myForm: any;
    .
    .
    .
}

이제 'myForm' 객체를 사용하여 클래스에 포함된 요소에 액세스할 수 있습니다.

Source

 */
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를 통해 DOM 요소에 대한 핸들을 얻을 수 있습니다.

constructor(private myElement: ElementRef) {
this.myElement.nativeElement // <- your direct element reference
}

두 번째 방법:

@Component({
  selector: 'my-app',
  template:
  `
  <input #input value="enterThere">
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  @ViewChild('input') input:ElementRef; 

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

주의: 이는 Angular 6 이상에는 적용되지 않습니다.ElementRef became became가 되었다ElementRef<T>TnativeElement.

만약 당신이 그것을 사용하고 있다면 추가하고 싶습니다.ElementRef하는 바와 같이, 여러분은 바로 ''이라는 하게 될 것입니다ElementRef 、 「 」 、「 」와 타입의 .

export declare class ElementRef {
  nativeElement: any;
}

nativeElement가 nativeElement인 브라우저 환경에서는 이 문제가 바보같습니다.HTMLElement.

이 문제를 해결하려면 다음 기술을 사용할 수 있습니다.

import {Inject, ElementRef as ErrorProneElementRef} from '@angular/core';

interface ElementRef {
  nativeElement: HTMLElement;
}

@Component({...}) export class MyComponent {
  constructor(@Inject(ErrorProneElementRef) readonly elementRef: ElementRef) { }
}

빠른 사용을 위한 최소 예시:

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

@Component({
  selector: 'my-app',
  template:
  `
  <input #inputEl value="hithere">
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  @ViewChild('inputEl') inputEl:ElementRef; 

  ngAfterViewInit() {
    console.log(this.inputEl);
  }
}
  1. 템플릿 참조 변수를 관심 DOM 요소에 배치합니다.이 예에서 이것은#inputEl에서<input>태그를 붙입니다.
  2. 컴포넌트 클래스에서는 @ViewChild 데코레이터를 통해 DOM 요소를 삽입합니다.
  3. 의 요소에 액세스합니다.ngAfterViewInit라이프 사이클 훅

주의:

DOM 요소를 조작하려면 요소에 직접 액세스하는 대신 Renderer2 API를 사용합니다.DOM에 대한 직접 액세스를 허용하면 응용 프로그램이 XSS 공격에 더욱 취약해질 수 있습니다.

바로 다음 형제자매를 얻으려면, 이것을 사용하세요.

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;
}

내부 컴포넌트의 경우*ngIf, 다른 접근법:

제가 선택하고 싶은 컴포넌트는 div의 *ngIf 스테이트먼트 안에 있고, 위의 @jsgoupil의 답변은 아마 효과가 있을 것입니다(@jsgoupil!). 하지만 결국 CSS를 사용하여 요소를 숨김으로써 *ngIf 사용을 피할 수 있는 방법을 찾았습니다.

[ className ]의 조건이 true이면 div가 표시되고 # 를 사용하여 컴포넌트의 이름을 붙이면 동작하며, 타이프스크립트 코드 내에서 선택할 수 있습니다.조건이 false일 경우 표시되지 않으며 선택할 필요가 없습니다.

컴포넌트:

@Component({
    selector: 'bla',
    templateUrl: 'bla.component.html',
    styleUrls: ['bla.component.scss']
})
export class BlaComponent implements OnInit, OnDestroy {
    @ViewChild('myComponentWidget', {static: true}) public myComponentWidget: any;
    @Input('action') action: ActionType; // an enum defined in our code. (action could also be declared locally)

constructor() {
   etc;
}

// this lets you use an enum in the HMTL (ActionType.SomeType)
public get actionTypeEnum(): typeOf ActionType {
    return ActionType;
}

public someMethodXYZ: void {
    this.myComponentWidget.someMethod(); // use it like that, assuming the method exists
}

그런 다음 bla.component.disc 파일에서 다음을 수행합니다.

<div [className]="action === actionTypeEnum.SomeType ? 'show-it' : 'do-not-show'">

    <my-component #myComponentWidget etc></my-component>
</div>
<div>
    <button type="reset" class="bunch-of-classes" (click)="someMethodXYZ()">
        <span>XYZ</span>
    </button>
</div>   

및 CSS 파일:

 ::ng-deep {
    .show-it {
         display: block;   // example, actually a lot more css in our code
    }
    .do-not-show {
        display: none'; 
    }
}

Angular Material을 사용하는 경우 cdkFocusInitial 디렉티브를 이용할 수 있습니다.

예:<input matInput cdkFocusInitial>

자세한 내용은 이쪽:https://material.angular.io/cdk/a11y/overview#regions

언급URL : https://stackoverflow.com/questions/32693061/how-can-i-select-an-element-in-a-component-template

반응형