我想创建过滤器组件,该组件将在具有不同内部组件数的不同位置使用。
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()); 最好的方法是什么?
答案 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>
这就是全部!谢谢你的关注!