Implement two-way data binding for custom property

2020-03-22 08:15发布

问题:

I see in primeng components the use something like ngModel (two-way data binding) style for some property like this

[(selection)]="selectedItem";

it 's look like

@Input() selection;
@Output() selection:EventEmitter<any> = new EventEmitter<any>();

how I can implement something like this and is it possible to do for more than single property like

 <component-a  [(selection)]="selectedItem"  [(data)]="selectedData"></component-a>

回答1:

Angular docs

<app-sizer 
  [(size)]="fontSizePx">
</app-sizer>

The two-way binding syntax is really just syntactic sugar for a property binding and an event binding. Angular desugars the binding into this:

<app-sizer
  [size]="fontSizePx"
  (sizeChange)="fontSizePx=$event">
</app-sizer>

To create two-way binding for property selection use:

@Input() selection;

// You have to follow this convention (For Output property)
// i.e. <propertyName><Change> like selectionChange

@Output() selectionChange:EventEmitter<any> = new EventEmitter<any>();

And to change selection in component as shown below:

changeSelection(newSelection)
{
    this.selection = newSelection;

    // emit change event to parent component
    this.selectionChange.emit(this.selection);  
}


回答2:

https://angular.io/guide/template-syntax#two-way-binding

The [(x)] syntax is easy to demonstrate when the element has a settable property called x and a corresponding event named xChange.

This means, you only need a corresponding selectionChange method on your child component. Hence, if you want the banana-in-a-box binding for your property selection of ParentComponent into ChildComponent, follow these steps:

  1. Include the following in your ChildComponent:

    @Input() selection;
    @Output() selectionChange = new EventEmitter<any>();
    
  2. In your ParentComponent template:

    <child [(selection)]="selection">
    

In summary, if your property name is x, you only need to name its corresponding EventEmitter to xChange and do the banana-in-a-box syntax for the child component [(x)] = "parentProperty" and Angular takes care of the rest.



回答3:

In your child component you have to implement two-way binding interface like this:

private _selection: any;
get selection(): any {
    return this._selection;
}
@Input()
set selection(value: any) {
    if(this._selection === value) {
        return;
    }
    this._selection = value;
    this.selectionChange.emit(this._selection);
}
@Output()
selectionChange = new EventEmitter<any>();

It's mandatory to name @Output filed by adding propertyNameChange to @Input name. So you can use it in your parent component temlate like this:

<mycomponent [(selection)]="fieldInParentComponent"></mycomponent>


回答4:

In your child component (component-a) you need an @output

@Output() change:EventEmitter = new EventEmitter();

and then you notify parent component about a changed value by

change.emit(newValue);

See also Angular2: https://stackoverflow.com/a/33220997/3710630