Chú thích góc 2 @ViewChild trả về không xác định


241

Tôi đang cố gắng học Angular 2.

Tôi muốn truy cập vào một thành phần con từ một thành phần cha mẹ bằng cách sử dụng Chú thích @ViewChild .

Đây là một số dòng mã:

Trong BodyContent.ts tôi có:

import {ViewChild, Component, Injectable} from 'angular2/core';
import {FilterTiles} from '../Components/FilterTiles/FilterTiles';


@Component({
selector: 'ico-body-content'
, templateUrl: 'App/Pages/Filters/BodyContent/BodyContent.html'
, directives: [FilterTiles] 
})


export class BodyContent {
    @ViewChild(FilterTiles) ft:FilterTiles;

    public onClickSidebar(clickedElement: string) {
        console.log(this.ft);
        var startingFilter = {
            title: 'cognomi',
            values: [
                'griffin'
                , 'simpson'
            ]}
        this.ft.tiles.push(startingFilter);
    } 
}

trong khi trong FilterTiles.ts :

 import {Component} from 'angular2/core';


 @Component({
     selector: 'ico-filter-tiles'
    ,templateUrl: 'App/Pages/Filters/Components/FilterTiles/FilterTiles.html'
 })


 export class FilterTiles {
     public tiles = [];

     public constructor(){};
 }

Cuối cùng ở đây các mẫu (như được đề xuất trong các ý kiến):

BodyContent.html

<div (click)="onClickSidebar()" class="row" style="height:200px; background-color:red;">
        <ico-filter-tiles></ico-filter-tiles>
    </div>

FilterTiles.html

<h1>Tiles loaded</h1>
<div *ngFor="#tile of tiles" class="col-md-4">
     ... stuff ...
</div>

Mẫu FilterTiles.html được tải chính xác vào thẻ ico-filter-gạch (thực sự tôi có thể thấy tiêu đề).

Lưu ý: lớp BodyContent được chèn vào bên trong một mẫu khác (Body) bằng DynamicComponetLoader: dcl.loadAsRoot (BodyContent, '# ico-bodyContent', kim phun):

import {ViewChild, Component, DynamicComponentLoader, Injector} from 'angular2/core';
import {Body}                 from '../../Layout/Dashboard/Body/Body';
import {BodyContent}          from './BodyContent/BodyContent';

@Component({
    selector: 'filters'
    , templateUrl: 'App/Pages/Filters/Filters.html'
    , directives: [Body, Sidebar, Navbar]
})


export class Filters {

    constructor(dcl: DynamicComponentLoader, injector: Injector) {
       dcl.loadAsRoot(BodyContent, '#ico-bodyContent', injector);
       dcl.loadAsRoot(SidebarContent, '#ico-sidebarContent', injector);

   } 
}

Vấn đề là khi tôi cố gắng ghi ftvào nhật ký giao diện điều khiển, tôi nhận được undefinedvà tất nhiên tôi gặp một ngoại lệ khi tôi cố gắng đẩy thứ gì đó vào trong mảng "gạch": 'không có thuộc tính gạch cho "không xác định"' .

Một điều nữa: Thành phần FilterTiles dường như được tải chính xác, vì tôi có thể thấy mẫu html cho nó.

Bất kì lời đề nghị nào? Cảm ơn


Có vẻ đúng. Có thể một cái gì đó với mẫu, nhưng nó không được bao gồm trong câu hỏi của bạn.
Günter Zöchbauer

1
Đồng ý với Günter. Tôi đã tạo một plunkr với mã của bạn và các mẫu liên quan đơn giản và nó hoạt động. Xem liên kết này: plnkr.co/edit/KpHp5Dlmppzo1LXcutPV?p=preview . Chúng tôi cần các mẫu ;-)
Thierry Templier

1
ftsẽ không được đặt trong hàm tạo, nhưng trong trình xử lý sự kiện nhấp chuột, nó sẽ được đặt.
Günter Zöchbauer

5
Bạn đang sử dụng loadAsRoot, có một vấn đề đã biết với phát hiện thay đổi. Chỉ để đảm bảo thử sử dụng loadNextToLocationhoặc loadIntoLocation.
Eric Martinez

1
Vấn đề là loadAsRoot. Một khi tôi thay thế với loadIntoLocationvấn đề đã được giải quyết. Nếu bạn đưa ra nhận xét của mình là câu trả lời, tôi có thể đánh dấu nó là được chấp nhận
Andrea Ialenti

Câu trả lời:


372

Tôi đã có một vấn đề tương tự và nghĩ rằng tôi sẽ đăng trong trường hợp người khác mắc lỗi tương tự. Đầu tiên, một điều cần xem xét là AfterViewInit; bạn cần đợi cho chế độ xem được khởi tạo trước khi bạn có thể truy cập @ViewChild. Tuy nhiên, tôi @ViewChildvẫn trả về null. Vấn đề là của tôi *ngIf. Lệnh *ngIfnày đã giết chết thành phần điều khiển của tôi nên tôi không thể tham khảo nó.

import {Component, ViewChild, OnInit, AfterViewInit} from 'angular2/core';
import {ControlsComponent} from './controls/controls.component';
import {SlideshowComponent} from './slideshow/slideshow.component';

@Component({
    selector: 'app',
    template:  `
        <controls *ngIf="controlsOn"></controls>
        <slideshow (mousemove)="onMouseMove()"></slideshow>
    `,
    directives: [SlideshowComponent, ControlsComponent]
})

export class AppComponent {
    @ViewChild(ControlsComponent) controls:ControlsComponent;

    controlsOn:boolean = false;

    ngOnInit() {
        console.log('on init', this.controls);
        // this returns undefined
    }

    ngAfterViewInit() {
        console.log('on after view init', this.controls);
        // this returns null
    }

    onMouseMove(event) {
         this.controls.show();
         // throws an error because controls is null
    }
}

Mong rằng sẽ giúp.

EDIT
Như được đề cập bởi @Ashg dưới đây , một giải pháp là sử dụng @ViewChildrenthay vì @ViewChild.


9
@kenecaswell Vậy bạn đã tìm ra cách tốt hơn để giải quyết vấn đề chưa. Tôi cũng đang phải đối mặt với cùng một vấn đề. Tôi có nhiều * ngNếu vậy phần tử đó sẽ chỉ ở sau tất cả đúng, nhưng tôi cần tham chiếu phần tử. Mọi cách để giải quyết vấn đề này>
monica

4
Tôi thấy rằng thành phần con là 'không xác định' trong ngAfterViewInit () nếu sử dụng ng If. Tôi đã cố gắng đặt thời gian chờ lâu nhưng vẫn không có hiệu quả. Tuy nhiên, thành phần con có sẵn sau này (tức là phản ứng với các sự kiện nhấp chuột, v.v.). Nếu tôi không sử dụng ng If và nó được định nghĩa như mong đợi trong ngAfterViewInit (). Có nhiều hơn về giao tiếp giữa Phụ huynh / Trẻ em tại đây angular.io/docs/ts/latest/cookbook/iêu
Matthew Hegarty

3
Tôi đã sử dụng bootstrap ngClass+ hiddenclass thay vì ngIf. Điều đó đã làm việc. Cảm ơn!
Rahmathullah M

9
Điều này không giải quyết được vấn đề, hãy sử dụng giải pháp bên dưới bằng cách sử dụng @ViewChildren để có được một tham chiếu đến kiểm soát trẻ em khi nó có sẵn
Ashg

20
Điều này chỉ chứng minh "vấn đề", phải không? Nó không đăng một giải pháp.
Miguel Ribeiro

144

Vấn đề như đã đề cập trước đó là vấn đề ngIfkhiến cho khung nhìn không được xác định. Câu trả lời là sử dụng ViewChildrenthay vì ViewChild. Tôi gặp vấn đề tương tự khi tôi không muốn hiển thị lưới cho đến khi tất cả dữ liệu tham chiếu đã được tải.

html:

   <section class="well" *ngIf="LookupData != null">
       <h4 class="ra-well-title">Results</h4>
       <kendo-grid #searchGrid> </kendo-grid>
   </section>

Mã thành phần

import { Component, ViewChildren, OnInit, AfterViewInit, QueryList  } from '@angular/core';
import { GridComponent } from '@progress/kendo-angular-grid';

export class SearchComponent implements OnInit, AfterViewInit
{
    //other code emitted for clarity

    @ViewChildren("searchGrid")
    public Grids: QueryList<GridComponent>

    private SearchGrid: GridComponent

    public ngAfterViewInit(): void
    {

        this.Grids.changes.subscribe((comps: QueryList <GridComponent>) =>
        {
            this.SearchGrid = comps.first;
        });


    }
}

Ở đây chúng tôi đang sử dụng ViewChildrenđể bạn có thể lắng nghe những thay đổi. Trong trường hợp này bất kỳ trẻ em với tài liệu tham khảo #searchGrid. Hi vọng điêu nay co ich.


4
Tôi muốn thêm rằng trong một số trường hợp khi bạn thử thay đổi, ví dụ. this.SearchGridcác thuộc tính bạn nên sử dụng cú pháp như setTimeout(()=>{ ///your code here }, 1); để tránh Ngoại lệ: Biểu thức đã thay đổi sau khi được kiểm tra
rafalkasa

3
Làm thế nào để bạn làm điều này nếu bạn muốn đặt thẻ #searchGrid của mình trên một phần tử HTML bình thường thay vì một phần tử Angular2? (Ví dụ: <div #searchGrid> </ div> và đây là bên trong khối * ng If?
Vern Jensen

1
đây là câu trả lời đúng cho trường hợp sử dụng của tôi Cảm ơn tôi cần truy cập vào một thành phần vì nó có sẵn thông qua ng If =
Frozen_byte

1
điều này hoạt động hoàn hảo trên các phản hồi ajax, bây giờ là các *ngIftác phẩm và sau khi kết xuất, chúng ta có thể lưu ElementRef từ các thành phần dinamic.
elporfirio

4
Cũng đừng quên gán nó cho một thuê bao và sau đó hủy đăng ký nó
tam.teixeira

63

Bạn có thể sử dụng một setter cho @ViewChild()

@ViewChild(FilterTiles) set ft(tiles: FilterTiles) {
    console.log(tiles);
};

Nếu bạn có một trình bao bọc ng If, setter sẽ được gọi với không xác định, và sau đó một lần nữa với tham chiếu một lần ng If cho phép nó hiển thị.

Vấn đề của tôi là một cái gì đó khác mặc dù. Tôi đã không bao gồm mô-đun chứa "FilterTiles" trong app.modules của mình. Mẫu không đưa ra lỗi nhưng tham chiếu luôn không được xác định.


3
Điều này không hiệu quả với tôi - Tôi nhận được cuộc gọi đầu tiên không xác định, nhưng tôi không nhận được cuộc gọi thứ hai với tham chiếu. Ứng dụng là một ng2 ... đây có phải là tính năng ng4 + không?
Jay Cummins

@Jay Tôi tin điều này là do bạn chưa đăng ký thành phần với Angular, trong trường hợp này FilterTiles. Tôi đã gặp vấn đề đó vì lý do đó trước đây.
Quốc hội

1
Hoạt động cho Angular 8 bằng cách sử dụng #paginator trên phần tử html và chú thích như@ViewChild('paginator', {static: false})
Qiteq

1
Đây có phải là một cuộc gọi lại cho những thay đổi của ViewChild không?
Yasser Nascimento

24

Điều này làm việc cho tôi.

Thành phần của tôi có tên 'my-thành phần', ví dụ, được hiển thị bằng cách sử dụng * ng If = "showMe" như vậy:

<my-component [showMe]="showMe" *ngIf="showMe"></my-component>

Vì vậy, khi thành phần được khởi tạo, thành phần vẫn chưa được hiển thị cho đến khi "showMe" là đúng. Do đó, tất cả các tham chiếu @ViewChild của tôi đều không được xác định.

Đây là nơi tôi đã sử dụng @ViewChildren và QueryList mà nó trả về. Xem bài viết góc cạnh trên QueryList và bản demo sử dụng @ViewChildren .

Bạn có thể sử dụng QueryList mà @ViewChildren trả về và đăng ký mọi thay đổi đối với các mục được tham chiếu bằng rxjs như được thấy bên dưới. @ViewChild không có khả năng này.

import { Component, ViewChildren, ElementRef, OnChanges, QueryList, Input } from '@angular/core';
import 'rxjs/Rx';

@Component({
    selector: 'my-component',
    templateUrl: './my-component.component.html',
    styleUrls: ['./my-component.component.css']
})
export class MyComponent implements OnChanges {

  @ViewChildren('ref') ref: QueryList<any>; // this reference is just pointing to a template reference variable in the component html file (i.e. <div #ref></div> )
  @Input() showMe; // this is passed into my component from the parent as a    

  ngOnChanges () { // ngOnChanges is a component LifeCycle Hook that should run the following code when there is a change to the components view (like when the child elements appear in the DOM for example)
    if(showMe) // this if statement checks to see if the component has appeared becuase ngOnChanges may fire for other reasons
      this.ref.changes.subscribe( // subscribe to any changes to the ref which should change from undefined to an actual value once showMe is switched to true (which triggers *ngIf to show the component)
        (result) => {
          // console.log(result.first['_results'][0].nativeElement);                                         
          console.log(result.first.nativeElement);                                          

          // Do Stuff with referenced element here...   
        } 
      ); // end subscribe
    } // end if
  } // end onChanges 
} // end Class

Hy vọng điều này sẽ giúp ai đó tiết kiệm thời gian và thất vọng.


3
Thật vậy, giải pháp của bạn dường như là cách tiếp cận tốt nhất được liệt kê cho đến nay. LƯU Ý Chúng tôi phải lưu ý rằng giải pháp 73 hàng đầu hiện đang bị ĐỔI ... vì chỉ thị: [...] tuyên bố KHÔNG còn được hỗ trợ trong Angular 4. IOW it KHÔNG hoạt động trong kịch bản Angular 4
PeteZaria

5
Đừng quên hủy đăng ký, hoặc sử dụng .take(1).subscribe(), nhưng câu trả lời tuyệt vời, cảm ơn bạn rất nhiều!
Blair Connolly

2
Giải pháp tuyệt vời. Tôi đã đăng ký các thay đổi ref trong ngAfterViewInit () thay vì ngOnChanges (). Nhưng tôi đã phải thêm một setTimeout để thoát khỏi ExpressionChangedAfterChecked lỗi
Josf

Điều này nên được đánh dấu là giải pháp thực tế. Cảm ơn rất nhiều!
platzhersh 28/03/19

10

Cách giải quyết của tôi là sử dụng [style.display]="getControlsOnStyleDisplay()"thay vì *ngIf="controlsOn". Khối ở đó nhưng nó không được hiển thị.

@Component({
selector: 'app',
template:  `
    <controls [style.display]="getControlsOnStyleDisplay()"></controls>
...

export class AppComponent {
  @ViewChild(ControlsComponent) controls:ControlsComponent;

  controlsOn:boolean = false;

  getControlsOnStyleDisplay() {
    if(this.controlsOn) {
      return "block";
    } else {
      return "none";
    }
  }
....

Có một trang trong đó danh sách các mục được hiển thị trong bảng hoặc mục chỉnh sửa được hiển thị, dựa trên giá trị của biến showList. Loại bỏ lỗi bảng điều khiển gây phiền nhiễu bằng cách sử dụng [style.display] = "! ShowList", kết hợp với * ng If = "! ShowList".
razvanone

9

Điều giải quyết vấn đề của tôi là đảm bảo staticđược đặt thành false.

@ViewChild(ClrForm, {static: false}) clrForm;

Khi statictắt, @ViewChildtham chiếu được cập nhật bởi Angular khi *ngIfchỉ thị thay đổi.


1
Đây gần như là một câu trả lời hoàn hảo, chỉ cần nói là một cách tốt để kiểm tra các giá trị không thể thực hiện được, vì vậy chúng tôi kết thúc với một cái gì đó như thế này: @ViewChild (ClrForm, {static: false}) đặt clrForm (clrForm: ClrForm) {if (clrForm) {this.clrForm = clrForm; }};
Klaus Klein

Tôi đã thử rất nhiều thứ và cuối cùng thấy điều này là thủ phạm.
Manish Sharma

8

Giải pháp của tôi cho việc này là thay thế *ngIf bằng [hidden]. Nhược điểm là tất cả các thành phần con đã có trong mã DOM. Nhưng làm việc cho yêu cầu của tôi.


5

Trong trường hợp của tôi, tôi đã có một trình thiết lập biến đầu vào bằng cách sử dụng ViewChildViewChildbên trong một lệnh *ngIf, vì vậy trình thiết lập đã cố gắng truy cập vào nó trước khi *ngIfkết xuất (nó sẽ hoạt động tốt mà không có *ngIf, nhưng sẽ không hoạt động nếu nó luôn được đặt thành đúng với *ngIf="true").

Để giải quyết, tôi đã sử dụng Rxjs để đảm bảo mọi tham chiếu đến sự ViewChildchờ đợi cho đến khi chế độ xem được bắt đầu. Đầu tiên, tạo một Chủ đề hoàn thành khi sau khi xem init.

export class MyComponent implements AfterViewInit {
  private _viewInitWaiter$ = new Subject();

  ngAfterViewInit(): void {
    this._viewInitWaiter$.complete();
  }
}

Sau đó, tạo một hàm lấy và thực thi lambda sau khi đối tượng hoàn thành.

private _executeAfterViewInit(func: () => any): any {
  this._viewInitWaiter$.subscribe(null, null, () => {
    return func();
  })
}

Cuối cùng, hãy đảm bảo các tham chiếu đến ViewChild sử dụng chức năng này.

@Input()
set myInput(val: any) {
    this._executeAfterViewInit(() => {
        const viewChildProperty = this.viewChild.someProperty;
        ...
    });
}

@ViewChild('viewChildRefName', {read: MyViewChildComponent}) viewChild: MyViewChildComponent;

1
Đây là một giải pháp tốt hơn nhiều so với tất cả các khoản giải quyết vô nghĩa
Liam

4

Nó phải hoạt động.

Nhưng như Günter Zöchbauer nói phải có một số vấn đề khác trong mẫu. Tôi đã tạo ra kinda có liên quan-Plunkr-Trả lời . Vui lòng kiểm tra bảng điều khiển của trình duyệt.

boot.ts

@Component({
selector: 'my-app'
, template: `<div> <h1> BodyContent </h1></div>

      <filter></filter>

      <button (click)="onClickSidebar()">Click Me</button>
  `
, directives: [FilterTiles] 
})


export class BodyContent {
    @ViewChild(FilterTiles) ft:FilterTiles;

    public onClickSidebar() {
        console.log(this.ft);

        this.ft.tiles.push("entered");
    } 
}

bộ lọcTiles.ts

@Component({
     selector: 'filter',
    template: '<div> <h4>Filter tiles </h4></div>'
 })


 export class FilterTiles {
     public tiles = [];

     public constructor(){};
 }

Nó hoạt động như một say mê. Vui lòng kiểm tra lại các thẻ và tài liệu tham khảo của bạn.

Cảm ơn...


1
Nếu sự cố giống như của tôi, để sao chép, bạn cần đặt * ngNếu trong mẫu xung quanh <filter> </ filter> .. Rõ ràng nếu ng If trả về sai, ViewChild sẽ không có dây và trả về null
Dan Đuổi theo

2

Điều này làm việc cho tôi, xem ví dụ dưới đây.

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

@Component({
    selector: 'app',
    template:  `
        <a (click)="toggle($event)">Toggle</a>
        <div *ngIf="visible">
          <input #control name="value" [(ngModel)]="value" type="text" />
        </div>
    `,
})

export class AppComponent {

    private elementRef: ElementRef;
    @ViewChild('control') set controlElRef(elementRef: ElementRef) {
      this.elementRef = elementRef;
    }

    visible:boolean;

    toggle($event: Event) {
      this.visible = !this.visible;
      if(this.visible) {
        setTimeout(() => { this.elementRef.nativeElement.focus(); });
      }
    }

}


2

Tôi đã có một vấn đề tương tự, trong đó ViewChildbên trong một switchmệnh đề không tải phần tử viewChild trước khi nó được tham chiếu. Tôi đã giải quyết nó theo cách nửa hack nhưng gói ViewChildtham chiếu theo cách setTimeoutthực thi ngay lập tức (tức là 0ms)


1

Giải pháp của tôi cho vấn đề này là di chuyển ngNếu từ bên ngoài thành phần con sang bên trong thành phần con trên một div bao bọc toàn bộ phần html. Bằng cách đó, nó vẫn bị ẩn khi cần, nhưng đã có thể tải thành phần và tôi có thể tham chiếu nó trong phần cha mẹ.


Nhưng đối với điều đó, làm thế nào bạn có được biến "hiển thị" của bạn trong cha mẹ?
Dan Chase

1

Tôi sửa nó chỉ thêm SetTimeout sau khi thiết lập hiển thị thành phần

HTML của tôi:

<input #txtBus *ngIf[show]>

Thành phần của tôi

@Component({
  selector: "app-topbar",
  templateUrl: "./topbar.component.html",
  styleUrls: ["./topbar.component.scss"]
})
export class TopbarComponent implements OnInit {

  public show:boolean=false;

  @ViewChild("txtBus") private inputBusRef: ElementRef;

  constructor() {

  }

  ngOnInit() {}

  ngOnDestroy(): void {

  }


  showInput() {
    this.show = true;
    setTimeout(()=>{
      this.inputBusRef.nativeElement.focus();
    },500);
  }
}

1

Trong trường hợp của tôi, tôi biết thành phần con sẽ luôn có mặt, nhưng muốn thay đổi trạng thái trước khi khởi tạo con để tiết kiệm công việc.

Tôi chọn thử nghiệm cho trẻ cho đến khi nó xuất hiện và thay đổi ngay lập tức, điều này giúp tôi tiết kiệm một chu kỳ thay đổi trên thành phần con.

export class GroupResultsReportComponent implements OnInit {

    @ViewChild(ChildComponent) childComp: ChildComponent;

    ngOnInit(): void {
        this.WhenReady(() => this.childComp, () => { this.childComp.showBar = true; });
    }

    /**
     * Executes the work, once the test returns truthy
     * @param test a function that will return truthy once the work function is able to execute 
     * @param work a function that will execute after the test function returns truthy
     */
    private WhenReady(test: Function, work: Function) {
        if (test()) work();
        else setTimeout(this.WhenReady.bind(window, test, work));
    }
}

Thông báo, bạn có thể thêm số lần thử tối đa hoặc thêm một vài độ trễ cho setTimeout. setTimeoutném hiệu quả vào cuối danh sách các hoạt động đang chờ xử lý.


0

Một loại phương pháp chung:

Bạn có thể tạo một phương thức sẽ đợi cho đến khi ViewChildsẵn sàng

function waitWhileViewChildIsReady(parent: any, viewChildName: string, refreshRateSec: number = 50, maxWaitTime: number = 3000): Observable<any> {
  return interval(refreshRateSec)
    .pipe(
      takeWhile(() => !isDefined(parent[viewChildName])),
      filter(x => x === undefined),
      takeUntil(timer(maxWaitTime)),
      endWith(parent[viewChildName]),
      flatMap(v => {
        if (!parent[viewChildName]) throw new Error(`ViewChild "${viewChildName}" is never ready`);
        return of(!parent[viewChildName]);
      })
    );
}


function isDefined<T>(value: T | undefined | null): value is T {
  return <T>value !== undefined && <T>value !== null;
}

Sử dụng:

  // Now you can do it in any place of your code
  waitWhileViewChildIsReady(this, 'yourViewChildName').subscribe(() =>{
      // your logic here
  })

0

Đối với tôi, vấn đề là tôi đã tham chiếu ID trên phần tử.

@ViewChild('survey-form') slides:IonSlides;

<div id="survey-form"></div>

Thay vì như thế này:

@ViewChild('surveyForm') slides:IonSlides;

<div #surveyForm></div>

0

Nếu bạn đang sử dụng Ionic, bạn sẽ cần sử dụng ionViewDidEnter()móc vòng đời. Ionic chạy một số nội dung bổ sung (chủ yếu liên quan đến hoạt hình) thường gây ra các lỗi không mong muốn như thế này, do đó cần một cái gì đó chạy sau ngOnInit , ngAfterContentInitv.v.


-1

Đây là một cái gì đó làm việc cho tôi.

@ViewChild('mapSearch', { read: ElementRef }) mapInput: ElementRef;

ngAfterViewInit() {
  interval(1000).pipe(
        switchMap(() => of(this.mapInput)),
        filter(response => response instanceof ElementRef),
        take(1))
        .subscribe((input: ElementRef) => {
          //do stuff
        });
}

Vì vậy, về cơ bản, tôi đặt một kiểm tra mỗi giây cho đến khi điều đó *ngIftrở thành sự thật và sau đó tôi thực hiện công việc của mình liên quan đến ElementRef.


-3

Giải pháp hiệu quả với tôi là thêm chỉ thị trong khai báo trong app.module.ts

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.