1

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"

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

8 Comments

but "this will trigger the (ngModelChange) when the onChange is called", as asked in 2), which property change in EditorComponent will trigger onChange?
@user1169587 You have to trigger the onChange method yourself, check this reference answer stack overflow answer
@user1169587 [(ngModel)]="_editor_status" (ngModelChange)="editorChange($event)" -> the _editor_status gets updated automatically when the onChange is called, because of two way data binding [()] also the editorChange method is called after the ngModel is updated.
@user1169587 [ngModel]="_editor_status" (ngModelChange)="editorChange($event)" It has only one way binding, so when user types, it does not update the _editor_status eventhough you call onChange but you have the option to update through (ngModelChange)="editorChange($event)"
@user1169587 ` [(ngModel)]="_editor_status"` the two way binding exists and the _editor_status when onChange is called, since you do not have ngModelChange you cannot trigger additional actions, when the ngModel is updated!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.