jensengar
jensengar

Reputation: 6167

Lifecycle Hook for after ngModel is loaded

I have a function that I need to run after this.value is set in my component. I tried using the lifecycle hook ngAfterContentInit() but this.value is either null or an empty string at that point.

I'm referencing my component like:

<add-select name="address" [options]="knownAddresses" [(ngModel)]="user.address"></add-select>

And my component looks like

const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => AddSelect),
    multi: true
};

@Component({
  selector: 'add-select',
  templateUrl: 'build/components/add-select/add-select.html',
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class AddSelect implements ControlValueAccessor {
  @Input() options: any[];

  // * NEED THIS TO RUN AFTER this.value IS CURRENT WHICH IS PASSED IN VIA ngModel
  private syncModelAndOptions() {
        if (this.options && this.value) {
            const modelOption = _.find(this.options, option => {
                return item == this.value || (option._id && this.value._id && option._id === this.value._id);
            });

            if (modelOption) {
                this.value = modelOption;
            } else {
                this.options.push(this.value);
            }
        }
    }

  //get accessor
  get value(): any {
    ...
  };

  //set accessor including call the onchange callback
  set value(v: any) {
    ...
  }

  //From ControlValueAccessor interface
  writeValue(value: any) {
    ...
  }

  //From ControlValueAccessor interface
  registerOnChange(fn: any) {
    ...
  }

  //From ControlValueAccessor interface
  registerOnTouched(fn: any) {
    ...
  }

Upvotes: 4

Views: 2666

Answers (3)

Avius
Avius

Reputation: 6244

The reason why you implement the ControlValueAccessor interface is so that your component would play nicely with Angular forms (both template-driven and reactive).

In template-driven forms (that's basically when you use ngModel), an update to ngModel eventually triggers a call to ControlValueAccessor.writeValue, which is supposed to know how to update the underlying form controls.

So a surefire way to run something as soon as this.value is set by the framework (i.e. ngModel) is to call it from within writeValue.

Upvotes: 1

Andrius
Andrius

Reputation: 957

Maybe using NgModel this way would help you. Inside your Component:

  import { NgModel } from '@angular/forms';

    /*...*/

  constructor(ngModel: NgModel) {

    ngModel.valueChanges.subscribe(() => {
      console.log('ngModel set')
    });
  }

Upvotes: 0

jmachnik
jmachnik

Reputation: 1120

You can use AfterViewChecked lifecycle to get the ngModel when it HAS an actual value. If you really want to use lifecycle hooks.

https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#afterview

But... You should use ngModelChange as it Is an ngModel event.

https://angular.io/docs/ts/latest/guide/forms.html (search for ngModelChange)

Upvotes: 2

Related Questions