So here is my parent form:
<form [ngFormModel]="formModel">
<ui-form-control *ngFor="#key of controlsKeys"
[control]="formModel.controls[key]"
[name]="key">
</ui-form-control>
</form>
here is my component:
@Component({
selector: 'ui-form-control'
})
@View({
template: `
<label>{{name}}: </label>
<input [ngFormControl]="control" [placeholder]="name">
`,
directives: [FORM_DIRECTIVES]
})
export class UiFormControl{
@Input() control: UiControl;
@Input() name: string;
constructor(){
}
}
I can see the Control value inside my ui-form-component, but when I've change it formModel-ComponentGroup doesn't update. So it looks like two way binding don't work here.
Actually if i'll remove my <ui-form-control>
and place simple <input>
tag instead it will work and formModel will update as expected.
I think that you should use two way binding here in your sub component with both @Input
and @Output
. The latter is notified the parent component that the control changes within the sub component. I think about something like that:
@Component({
selector: 'ui-form-control'
template: `
<label>{{name}}: </label>
<input [ngFormControl]="control" (change)="inputChanged()" [placeholder]="name">
`,
directives: [FORM_DIRECTIVES]
})
export class UiFormControl{
@Input() control: UiControl;
@Output() controlChange: EventEmitter;
@Input() name: string;
constructor(){
this.controlChange = new EventEmitter();
}
inputChanged() {
this.controlChange.emit(this.control);
}
}
I used an intermediate approach for the field of my forms by leveraging ng-content
.
@Component({
selector: 'field',
template: `
<div class="form-group form-group-sm" [ngClass]="{'has-error':control && !control.valid}">
<label for="for"
class="col-sm-3 control-label">{{label}}</label>
<div #content class="col-sm-8">
<ng-content ></ng-content>
<span *ngIf="control && !control.valid" class="help-block text-danger">
<span *ngIf="control?.errors?.required">The field is required</span>
</span>
</div>
</div>
`
})
export class FormFieldComponent {
@Input()
label: string;
@Input()
state: Control;
}
And its use within the parent component:
<form [ngFormModel]="companyForm">
<field label="Name" [state]="companyForm.controls.name">
<input [ngFormControl]="companyForm.controls.name"
[(ngModel)]="company.name"/> {{name.valid}}
</field>
</form>
That way the inputs, selects, textareas remain managed within the parent component but field components tackles field formatting (structure for Bootstrap3 for example) and leverage controls to display errors if any. This way you don't need two way binding anymore for field component and the latter is more generic ;-)
Hope it helps you, Thierry
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With