我正在尝试通过第二个子组件传递ngModel,但是一旦这样做,它将无法正常工作。 要传递ngModel,请使用以下抽象类:
export abstract class AbstractValueAccessor implements ControlValueAccessor {
_value: any = '';
get value(): any { return this._value; };
set value(v: any) {
if (v !== this._value) {
this._value = v;
this.onChange(v);
}
}
writeValue(value: any) {
this._value = value;
this.onChange(value);
}
onChange = (_) => { };
onTouched = () => { };
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
}
export function MakeProvider(type: any) {
return {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => type),
multi: true,
};
}
然后我有一个扩展该抽象类的输入组件:
@Component({
selector: 'app-input',
templateUrl: './input.component.html',
styleUrls: ['./input.component.scss'],
providers: [MakeProvider(InputComponent)],
})
export class InputComponent extends AbstractValueAccessor {
@Input('displaytext') displaytext: string;
@Input('placeholder') placeholder: string;
}
使用此模板:
<ion-input
[(ngModel)]="value"
type="text"
></ion-input>
如此出色的作品:
<app-input [(ngModel)]="value"></app-input>
但是,当我围绕这种组件制作一个组件时:
@Component({
selector: 'app-form-input-item',
templateUrl: './form-input-item.component.html',
styleUrls: ['./form-input-item.component.scss'],
providers: [MakeProvider(FormInputItemComponent)],
})
export class FormInputItemComponent extends AbstractValueAccessor {
@Input() position: string;
}
并以这种方式使用它:
<app-item>
<app-label [position]="position"><ng-content></ng-content></app-label>
<app-input [(ngModel)]="value"></app-input>
</app-item>
然后在其父级中将其命名为:
<app-form-input-item *ngFor='let item of data' position="floating" [(ngModel)]="item.value">
<b>{{item.title}}</b>
</app-form-input-item>
ngModel为空。我可以对其进行编辑,但它会发生变化,但某些内容会不断清空。如果我将<app-input>
更改为<ion-input>
,它将再次起作用。我在这里做什么错了?
更新:
这是我的应用程序项:
<ion-item>
<ng-content></ng-content>
</ion-item>
Stackblitz(感谢@GaurangDhorda):https://stackblitz.com/edit/angular-uuoahx
答案 0 :(得分:1)
您可以在此StackBlitz Link
中找到完整的工作示例在这里,我们正在使用Atom
创建自定义的单个ControlValueAccessor
输入组件。根据{{3}}, Input.component.html 是...。
<input type="text" [(ngModel)]="value">
然后,我们正在创建名为AbstractValueAccessor
的自定义类,并在其中实现ControlValueAccessor
。这样一来,每当需要将任何组件转换为ControlValueAccessor
时,我们都将AbstractValueAccessor
类扩展为component.ts类。因此 input.component.ts 是...
export class InputComponent extends AbstractValueAccessor {
ngOnInit() {
}
}
自定义 AbstractValueAccessor.ts 是...
import { Component, forwardRef, HostBinding, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const noop = () => {
};
export abstract class AbstractValueAccessor implements ControlValueAccessor {
//The internal data model
private innerValue: any = '';
//Placeholders for the callbacks which are later provided
//by the Control Value Accessor
private onTouchedCallback: () => void = noop;
private onChangeCallback: (_: any) => void = noop;
//get accessor
get value(): any {
return this.innerValue;
};
//set accessor including call the onchange callback
set value(v: any) {
if (v !== this.innerValue) {
this.innerValue = v;
this.onChangeCallback(v);
}
}
//Set touched on blur
onBlur() {
this.onTouchedCallback();
}
//From ControlValueAccessor interface
writeValue(value: any) {
if (value !== this.innerValue) {
this.innerValue = value;
}
}
//From ControlValueAccessor interface
registerOnChange(fn: any) {
this.onChangeCallback = fn;
}
//From ControlValueAccessor interface
registerOnTouched(fn: any) {
this.onTouchedCallback = fn;
}
}
export function MakeProvider(type: any) {
return {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => type),
multi: true,
};
}
然后必须在您的 input.component.ts 中提供MakeProvider()
import {AbstractValueAccessor,MakeProvider} from '.././abstract-value-accessor';
@Component({
selector: 'app-input',
templateUrl: './input.component.html',
styleUrls: ['./input.component.css'] ,
providers: [MakeProvider(InputComponent)],
})
在 form-input-item 组件中使用此自定义输入组件。根据原子设计模式,这称为Molecules
。
<app-item>
<app-input [(ngModel)]="value"></app-input>
<ng-content></ng-content>
</app-item>
这是您的主要app.component.html ,在Atomic Design中称为Organisms
。
<div style="box-shadow : 1px 2px 6px ; padding:1rem; margin: 0 auto; width:50vw" >
<app-form-input-item [ngStyle]="{'margin': ' 0 auto' }"
*ngFor="let galaxy of galaxies; let in=index;" [(ngModel)]="galaxy.name">
<div style="box-shadow: 1px 1px 3px #123456; margin:1em; padding:1em; word-break: break-word;">
{{galaxy.name}}
</div>
<hr style="border: .5px solid red">
</app-form-input-item>
<app-form-input-item [(ngModel)]="bh" ></app-form-input-item>
您 app.component.ts 是..
export class AppComponent {
name = 'Angular';
galaxies = [
{id:1,name:'Milky Way'},
{id:2,name:'LMC'},
{id:3,name:''},
{id:4,name:'Cigar Galaxy'}
];
}