user1169587
user1169587

Reputation: 1340

Angular Nested Form ngModel meaning

Given the following code snippet:

@Component({
  selector: 'app-editor',
  templateUrl: './editor.component.html',
  styleUrls: ['./editor.component.scss'],
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => EditorComponent),
    multi: true
  }]
})
export class EditorComponent implements OnInit, OnDestroy, AfterViewInit, ControlValueAccessor{
    public _editor_status: { 'opened': boolean, 'editable': boolean, 'new': boolean, 'cont': boolean, 'data': any };
    @Input() form: FormDto = null;
    public test:any;
    
    updateChanges() {
        .....
    }
    writeValue(value: any): void {
        .....
    }
    onChange: (_: any) => void = (_: any) => { };
    onTouched: () => void = () => { };
    registerOnChange(fn: any): void {
        this.onChange = fn;
    }
    registerOnTouched(fn: any): void {
        this.onTouched = fn;
    }
    ......
}

RecordManager.component.html
<app-editor *ngIf="_editor_status.opened" [editor_id]="'f41editor'"
                [form]="form"               
                [(ngModel)]="_editor_status"
                (ngModelChange)="editorChange($event)"
                [ngModelOptions]="{standalone: true}">
</app-editor>

RecordManager.component.ts
....
@Component({
  selector: 'app-record-manager',
  templateUrl: './Record-manager.component.html',
  styleUrls: ['./Record-manager.component.scss']
})

export class RecordManagerComponent implements OnInit, OnDestroy {
    public _editor_status: { 'opened': boolean, 'editable': boolean, 'new': boolean, 'cont': boolean, 'data': any }
    = { opened: false, editable: false, new: false, cont: false, data: null };
    private form: FormDto;
    ......
}

Both RecordManagerComponent and EditorComponent is anuglar form, with EditorComponent nested inside RecordMangerComponent, for the code RecordManager.component.html

<app-editor *ngIf="_editor_status.opened" [editor_id]="'f41editor'"
                [form]="form"               
                [(ngModel)]="_editor_status"
                (ngModelChange)="editorChange($event)"
                [ngModelOptions]="{standalone: true}">
</app-editor>
  1. for
    [(ngModel)]="_editor_status"

I know the right hand side "_editor_status" mean _editor_status in RecordManagerComponent, but for the left hand side, [(ngModel)], does it surely mean property _editor_status in EditorComponent as it has the same name as in the right hand side of [(ngModel)]="_editor_status", or the meaning of [(ngModel)] depends on writeValue(value:any) function? If writeValue function assign the parameter value to test property of EditorComponent, then [(ngMode)] mean test property of EditorComponent?

  1. for
(ngModelChange)="editorChange($event)"

what property in EditorComponent with trigger ngModelChange? Or what property in EditorComponent will trigger this.onChange in EditorComponent? the same property as in [(ngModel)]?

  1. as already have
(ngModelChange)="editorChange($event)"

then is

[(ngModel)]="_editor_status"

should change to

[ngModel]="_editor_status"

Upvotes: 1

Views: 64

Answers (1)

Naren Murali
Naren Murali

Reputation: 56052

As far as I know, the [(ngModel)]="_editor_status" will trigger the writeValue of the custom form component (EditorComponent), this is the interface used to update the internal property of EditorComponent.

When the onChange is registered in the custom form component, this will trigger the (ngModelChange) when the onChange is called.

You have to call the onChange method in your custom form component. You can use existing javascript change events like (input) or (change) to trigger the onChange method.

Reference SO Answer implementing custom form control

Think of the provider NG_VALUE_ACCESSOR and the ControlValueAccessor as a way of abstracting the calling/binding of ngModel and ngModelChange, so that we need not worry about the internal workings. We just need to implement this interface properly and Template Driven and Reactive forms can be used on this custom form component.


  1. If you want a change to happen, even after the ngModel is updated. Then use [(ngModel)]="_editor_status" and (ngModelChange)="editorChange($event)"

  2. If you want a change to happen, which determines whether to update the ngModel instead of directly updating using two way binding, then go for [ngModel]="_editor_status" and (ngModelChange)="editorChange($event)". Here the _editor_status from the component. But when the user inputs anything, the ngModelChange triggers, where we need to manually update the _editor_status, with the user input value, which is received through $event.

Upvotes: 1

Related Questions