获取在HTML模板中声明的组件内的组件

时间:2017-10-18 09:02:35

标签: angular angular2-components

我想创建过滤器组件,该组件将在具有不同内部组件数的不同位置使用。

filter.component.html

<select-filter name="somename" ></select-filter>
<input-filter name="somename"></input-filter>
...

选择过滤器和输入过滤器是实现Interface FilterItem

的组件
export interface FilterItem{
  name: string;
  getValue() : any;
}

我想在filter.component.ts中获取每个组件的实例(例如调用getValue()); 最好的方法是什么?

2 个答案:

答案 0 :(得分:1)

听起来你想要创建表单控件的组件。

如果我是对的,请尝试使用ControlValueAccessor代替: https://angular.io/api/forms/ControlValueAccessor

有很多关于如何使用它们的例子。 以下是从https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html

获取的实施示例
export function createCounterRangeValidator(maxValue, minValue) {
  return (c: FormControl) => {
    let err = {
      rangeError: {
        given: c.value,
        max: maxValue || 10,
        min: minValue || 0
      }
    };

  return (c.value > +maxValue || c.value < +minValue) ? err: null;
  }
}

@Component({
  selector: 'counter-input',
  template: `
    <button (click)="increase()">+</button> {{counterValue}} <button (click)="decrease()">-</button>
  `,
  providers: [
    { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CounterInputComponent), multi: true },
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => CounterInputComponent), multi: true }
  ]
})
export class CounterInputComponent implements ControlValueAccessor, OnChanges {

  propagateChange:any = () => {};
  validateFn:any = () => {};

  @Input('counterValue') _counterValue = 0;
  @Input() counterRangeMax;
  @Input() counterRangeMin;

  get counterValue() {
    return this._counterValue;
  }

  set counterValue(val) {
    this._counterValue = val;
    this.propagateChange(val);
  }

  ngOnChanges(inputs) {
    if (inputs.counterRangeMax || inputs.counterRangeMin) {
      this.validateFn = createCounterRangeValidator(this.counterRangeMax, this.counterRangeMin);
      this.propagateChange(this.counterValue);
    }
  }

  writeValue(value) {
    if (value) {
      this.counterValue = value;
    }
  }

  registerOnChange(fn) {
    this.propagateChange = fn;
  }

  registerOnTouched() {}

  increase() {
    this.counterValue++;
  }

  decrease() {
    this.counterValue--;
  }

  validate(c: FormControl) {
    return this.validateFn(c);
  }
}

答案 1 :(得分:0)

解决方案是下一步

1)父组件使用@ContentChildren或@ViewChildren获取子组件的数据,其中参数为QueryList。参数是抽象类的一个重要的事情。我们无法在那里使用界面。实际上我们也不能使用抽象类,但我们在嵌套组件中使用提供程序。 就我而言,它是

export class FilterComponent{
   @ContentChildren(FilterItem) filterItems: QueryList<FilterItem>;
   constructor() {}

   getItems(){
      console.log(this.filterItems);
      this.filterItems.forEach( i => {
        console.log( 'My name is ' + i.name + 'My value is ' + i.getValue());
      });
   }
}

2)嵌套组件应扩展抽象类,并将此抽象类声明为提供者。 在我的情况下

@Component({
  selector: 'app-string-filter-item',
  templateUrl: './string-filter-item.component.html',
  styleUrls: ['./string-filter-item.component.scss'],
  providers: [{provide: FilterItem, useExisting: forwardRef(() => StringFilterItemComponent)}]
})
export class StringFilterItemComponent extends FilterItem {

  selectValue: string;

  @Input()
  name:string;

  caption: 'SHow me smt';

  getValue(){
     return this.selectValue;
  }
}

的字符串滤波器-item.component.html

<p>
  <input type="text" [(ngModel)]="selectValue">
</p>

filter.component.html

<div class="filter-wr">
   <ng-content></ng-content>
</div>

在任何地方使用过滤器组件 (选择字符串组件是我使用的另一个组件)

<app-filter>
  <app-select-filter-item name="first"></app-select-filter-item>
  <app-string-filter-item name="second"></app-string-filter-item>
  <app-select-filter-item name="third"></app-select-filter-item>
  <app-string-filter-item name="fourth"></app-string-filter-item>
</app-filter>

这就是全部!谢谢你的关注!