我有以下组件:
import { Component, Input, Output, OnInit, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'counter',
templateUrl: './counter.component.html',
styleUrls: ['./counter.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CounterComponent {
ngOnInit()
{
this.defaultCount = this.count;
}
@Input()
count: number;
defaultCount: number;
@Output()
change: EventEmitter<number> = new EventEmitter<number>();
increment() {
this.count++;
this.change.emit(this.count);
}
decrement() {
if(this.count > 0)
{
this.count--;
this.change.emit(this.count);
}
}
reset()
{
this.count = this.defaultCount;
this.change.emit(this.count);
}
}
模板:
<span>{{count}}</span>
<div>
<button (click)="increment()">Increment</button>
<button (click)="decrement()">Decrement</button>
<button (click)="reset()">Reset</button>
</div>
在parrent组件中,我使用此组件,如下所示。 它是模板:
<counter [count]="5" (change)="countChange($event)"></counter>
<counter [count]="10" (change)="countChange($event)"></counter>
<button (click)="resetAll()">Reset All</button>
和代码:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app works!';
countChange(event) {
//this.myCount = event;
}
resetAll(event)
{
}
}
在resetAll(event)
函数中,我想为页面上此组件的每个实例设置[count]
,就像在增加,减少或重置事件之前一样。
如何仅列出此组件的实例并通过调用每个实例的reset函数重置[count]
属性?我必须为每个组件添加相同的Id并按ID查找或者我可以按类型查找组件?就我而言,类型为CounterComponent
。
答案 0 :(得分:2)
您应该在父组件上初始化counters
值,在您的示例中,AppComponent:
成分</ P>
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
firstCounter: number = 5;
secondCounter: number = 10;
resetAll(event) {
this.firstCounter = 5;
this.secondCounter = 10;
}
}
HTML
<counter [count]="firstCounter" (change)="countChange($event)"></counter>
<counter [count]="secondCounter" (change)="countChange($event)"></counter>
<button (click)="resetAll()">Reset All</button>
我能想到的最好的方法是Observer / Observable模式。
所以我创建了一个CounterObserverService
,你的CounterComponent
会自己注册,然后他们的状态将由Service
管理,看看:
CounterComponent
import {
CounterObservable,
CounterObserverService
} from './counter-observer.service';
import {
Component,
Input,
Output,
OnInit,
OnDestroy,
EventEmitter,
ChangeDetectionStrategy
} from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'counter',
template: `
<span>{{ count }}</span>
<div>
<button (click)="increment()">Increment</button>
<button (click)="decrement()">Decrement</button>
<button (click)="reset()">Reset</button>
</div>
`
})
export class CounterComponent implements OnInit, OnDestroy {
@Input()
count: number;
private counterObservable: CounterObservable;
private counterSubscription: Subscription;
@Output()
change: EventEmitter<number> = new EventEmitter<number>();
constructor(
private counterObserverService: CounterObserverService
) {}
ngOnInit() {
this.counterObservable = this.counterObserverService.register(this.count);
this.counterSubscription = this.counterObservable.currentCount.subscribe((counte) => {
this.count = counte;
this.change.emit(this.count);
})
}
ngOnDestroy() {
this.counterSubscription.unsubscribe();
this.counterObserverService.unregister(this.counterObservable);
}
increment() {
this.updateCurrentCount(1);
}
decrement() {
this.updateCurrentCount(-1);
}
reset() {
this.counterObserverService.reset(this.counterObservable.id);
}
private updateCurrentCount(increment: number) {
const newCount = this.count + increment;
if (newCount > 0) {
this.counterObservable.currentCount.next(newCount);
}
}
}
CounterObserverService
import { Injectable } from '@angular/core';
import { v4 as uuid } from 'uuid';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
export interface CounterObservable {
id: string;
initialCount: number;
currentCount: BehaviorSubject<number>;
}
@Injectable()
export class CounterObserverService {
private counters: CounterObservable[] = [];
constructor() {}
register(initialCount: number): CounterObservable {
const counterObservable = {
id: uuid(),
initialCount,
currentCount: new BehaviorSubject<number>(initialCount)
}
this.counters.push(counterObservable);
return counterObservable;
}
unregister(counterObservable: CounterObservable): void {
const index = this.counters.indexOf(counterObservable);
if (index > -1) {
this.counters.splice(index, 1);
}
}
reset(id: string): void {
const counterObservable = this.counters.find((item) => item.id === id);
if (counterObservable) {
counterObservable.currentCount.next(counterObservable.initialCount);
}
}
resetAll() {
this.counters.forEach((counterObservable) => {
counterObservable.currentCount.next(counterObservable.initialCount);
});
}
}
不要忘记在AppModule的providers
数组中注册此服务
AppComponent
import { Component } from '@angular/core';
import { CounterObserverService } from './counter/counter-observer.service';
@Component({
selector: 'app-root',
template: `
<counter *ngFor="let counter of counters" [count]="counter"
(change)="countChange($event)"></counter>
<button (click)="addCounter()">Add</button>
<button (click)="removeCounter()">Remove</button>
<button (click)="resetAll()">Reset All</button>
`
})
export class AppComponent {
counters = [1, 2, 3];
constructor(
private counterObserverService: CounterObserverService
) {}
addCounter() {
this.counters.push(this.counters.length + 1);
}
removeCounter() {
this.counters.pop();
}
countChange(event) {}
resetAll() {
this.counterObserverService.resetAll();
}
}
答案 1 :(得分:0)
您可以使用@ViewChildren。 对于你的例子: 添加父组件
@ViewChildren(counterComponent) counters: QueryList<counterComponent>
this.counters.forEach(counterInstance => counterInstance.count=5);