Angular - Two way binding input property to component with getters / setters

3.7k views Asked by At

I have the following angular components:

ComponentB which has an input property, and componentA which insert componentB in the template file. The code looks as the following:

componentA.ts:

export class ComponentA{
    isOpen: boolean;

    methodA() {
        this.isOpen = false;
        // do some work
    }
}

componentA.html:

<componentB [(open)]="isOpen"></componentB >

ComponentB.ts:

@Component({
    selector: 'componentB',
    templateUrl: 'ComponentB .html',
    encapsulation: ViewEncapsulation.None,
})
export class ComponentB {

    private _open: boolean = false;

    @Input('open') set open(value: boolean) {
        if (open === this._open) {
            return;
        }
        if (open) {
            // doSomething()
        } else {
            // doSomethingElse()
        }
        this._open = open;
    }

    get open() {
        return this._open;
    }
}

The issue is that isOpen property doesn't seems to reflect the current value of open property, although two way binding was specified.

Why does it happens? How can it be fixed?

2

There are 2 answers

0
Mujadid Mughal On BEST ANSWER

Two way binding is a special syntax that angular provides to set the value of a component and listen to value changes at the same time.

For this purpose special syntax (Banana in a box) "[()]" is used. Please find the official angular documentation about this here.

In a nutshell, you'll have to provide one property with @Input() decorator, and one property with @Output() decorator. The @Output() property will have the word Change appended to it. So if the @Input property name was x then the output property name shall be xChange. And whenever the underlying bound property is changed, using the EventEmitter of the output property, let the parent component listen to the change (hence two way binding implemented).

In your case your code would update like this

  @Input('open') set open(value: boolean) {
        if (value === this._open) {
            return;
        }
        if (open) {
            // doSomething()
        } else {
            // doSomethingElse()
        }
        this._open = value;
        this.openChange.emit(this._open); //open value set, the updated value is emitted using the output property.
    }
    get open() {
        return this._open;
    }
      @Output('openChange')  //the output property added
      openChange = new EventEmitter<boolean>();

Please find the Stack Blitz link.

4
Talha Akca On
private _open= false;

@Input('open') set open(value: boolean) {
    if (value=== this._open) {
        return;
    }
    if (value) {
        // doSomething()
    } else {
        // doSomethingElse()
    }
    this._open = value;
}

get open() {
    return this._open;
}

can you try this ?

btw @Input() open : boolean = false; is a lint mistake. when you assign = false to value it's type will automatically assign as boolean you don't have to specify it