0

I have a directive that seems to have broken when I upgraded to Angular 9 and build with Ivy turned on.

I made a simplified version of the directive to illustrate what the problem is:

import { Directive, Input, forwardRef, OnInit } from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";

@Directive({
    selector: '[my-directive]',
    providers: [MyDirective,
    {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => MyDirective),
        multi: true,
    }]
})
export class MyDirective implements OnInit, ControlValueAccessor {
    @Input("my-directive") MyDirective: any;

    test: any;
    test2: any = { id: 2 }

    ngOnInit() {
        this.test = { id: 1 }
    }

    private propagateChange = (_: number) => { };

    public writeValue(obj: number | string) {
        console.log(this.test); // <- This is undefined when Ivy is on and { id: 1 } with Ivy off
        console.log(this.test2);  // <- This works
    }

    public registerOnChange(fn: any) {
        this.propagateChange = fn;
    }

    public registerOnTouched() { }
}

and the HTML

<input type="text" [my-directive]='{ "param1": "false"  }' [(ngModel)]="tempVal" />

It looks like my directive is being created twice. Once for the [my-directive] and once for the [(ngModel)]

Any ideas what changed and how to fix this?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Scottie
  • 11,050
  • 19
  • 68
  • 109

1 Answers1

0

I found the problem.

I was doing this in the providers:

providers: [MyDirective,
{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => MyDirective),
    multi: true,
}]

Having the MyDirective there was creating 2 instances of the component. The first instance was the component, the second was the ngModel. They didn't play nice together.

Removing that from the providers fixed it.

Scottie
  • 11,050
  • 19
  • 68
  • 109