如何在Angular2中为页面上的所有组件实例设置值?

时间:2017-07-03 11:54:26

标签: angular loops components

我有以下组件:

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

2 个答案:

答案 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);