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 ;)

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.