angularngmodelngx-quill

How to access [(ngModel)] from another component?


I have a common component which holds ngx-quill component. Which I want to call in several other components for getting editor instead of input field. I was successful in making that work. But I am using ngModels to do two way data binding, which can not be used on Div. How can I access them in my common component.

So this is my common component :

common_component.html

<quill-editor>
</quill-editor>

Common_component.ts:

import { Component } from '@angular/core';
import * as _ from 'underscore';

@Component({
    selector: 'app-quill-editor',
    templateUrl: './common_component.html'
})

export class CommanQuillComponent {

    constructor(
    ) {}

}

This is where I am calling it :

main_component.html

<div>
    <app-quill-editor
        id="float-input"
        placeholder=" "
        name="myRange"
        step="1"
        [(ngModel)]="myVar"
    ></app-quill-editor>
</div>

main_component.ts holds nothing but variable declaration.

Now problem here is ngModel can not be used on div(it will throw error), html considers as div tag, then calls inside it, I want to have that ngModel on , I can not put it manually as this is going to be used as common component.

Please help me understand how can I achieve this data binding ?

Thank you for support and let me know if more understandable code should be added to the post.


Solution

  • What your looking for is ControlValueAccessor for implementing custom form control so that two-way data binding can work on custom component.

    Let's say you binded value variable on the quill-editor:

    <quill-editor [ngModel]="value" (ngModelChange)="onChange($event)"></quill-editor>
    
    @Component({
      ...
      providers: [
        { 
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => CommanQuillComponent),
          multi: true
        }
      ]
    })
    export class CommanQuillComponent implements ControlValueAccessor() {
       value: string = '';
    
       ...
       // Add other properties as Input
       @Input()
       placeholder: string;
    
       ...
    
       propagateChange = (_: any) => {};
       registerOnChange(fn) {
        this.propagateChange = fn;
      }
      
      writeValue(value: string) {
         this.value = value; // <- you receive the value which is binded to this component here
      }
    
      onChange(event: string) {
         this.value = event;
         this.propagateChange(event); // <- you export the value so the binded variable is updated
      }
    }
    

    Now you can use two-way data binding on that CommanQuillComponent:

    <div>
        <app-quill-editor
            id="float-input"
            placeholder=" "
            name="myRange"
            step="1"
            [(ngModel)]="myVar"
        ></app-quill-editor>
    </div>
    

    There are many articles online that you can read to get more details:

    https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html

    https://javascript-conference.com/blog/angular-reactive-forms-building-custom-form-controls/

    https://codinglatte.com/posts/angular/angular-build-custom-form-control/