2

I have created a custom input formControl, so I need to get/set its value via [(ngModel)]:

import { Component, Injector, OnInit, forwardRef } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, FormGroup } from '@angular/forms';

@Component({
    selector: 'time-picker',
    template:
        `<input type="text" class="clockpicker" [formControl]="selectedTime" />`,
    providers: [{
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => TimePickerComponent),
        multi: true,
    }]
})

export class TimePickerComponent implements OnInit, ControlValueAccessor {
    
    selectedTime = new FormControl('');

    constructor() { }

    ngAfterViewInit() {
        this.scriptLoader.load(
            'assets/clockpicker/clockpicker.js'
        );
    }
 
    writeValue(obj: any): void {
        if (this.selectedTime) {
            this.selectedTime.setValue(obj);
        }
    }

    registerOnChange(fn: any): void {
        this.selectedTime.valueChanges.subscribe(fn);
    }

    registerOnTouched(fn: any): void {
        this.onTouched = fn;
    }

}

As you can see I have loaded a JavaScript third-party named clockpicker.js. (It's just a simple clock picker), and here its code:

$(document).ready(function () {
    $('.clockpicker').each(function (index, element) {
        $(element).clockpicker({
            afterDone: function () {
                $(element).find('input[type="text"]').change();
            }
        });
    });
});

Here is my problem:

When I directly type in this input so I can get the inserted value by [(ngModel)], but as you can see when the jQuery function fill the input value I can't get the filled value by [(ngModel)]. I know it's because it can't fire the registerOnChange event in Angular life cycle even I use

$(element).find('input[type="text"]').change();

Nothing happen.

1 Answer 1

2

Angular can't know about changes that happen outside its zone. This means that you should tell to your Angular app that needs to run a change detection cycle to see if anything requires updating.

In your case, you should initialize the clock-picker inside your component and detect changes with ChangeDetectorRef. Please read more about NgZone too that is useful to execute something that's outside you Angular zone.

Can be useful:

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

4 Comments

Thanks, I've tried ChangeDetectorRef too, but again couldn't realizes the change, as your perspective, where do I call the ChangeDetection() ?
I think in the afterDone or in the specific method that's called on changes by the colorpicker library but you should communicate to your custom control about that change too I think.
Thanks again dear, let me read your links instruction and try again.
No problem. let me know if you have trouble and, if you can find a solution feel free to reply here ;)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.