Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom input and output on same name in Angular2 2 way binding

I know how to fix my component using a different name for the output value of this component.

let me share my code

import {Component, Input, Output, EventEmitter} from '@angular/core'; import {TranslationPipe} from "../pipes/translation.pipe";

@Component({   selector: 'msisdn-confirm',   template: `   <div class="msisdn-confirm">     <div>       <input type="text" [(ngModel)]="m1">     </div>     <div>       <input type="text" [(ngModel)]="m2">     </div>     <p class="error">{{message}}</p>   </div> ` }) export class MsisdnConfirm {   message:string;   @Output('mobile') emitter: EventEmitter<string> = new EventEmitter<string>();   @Input('mobile') set setMobileValue(value) {     this.msisdn_confirm = this.msisdn = value;   }    set m1(value) {     this.msisdn = value;     if (this.valid()) {       console.log('emit' + this.msisdn);       this.emitter.emit(this.msisdn);     }   }    set m2(value) {     this.msisdn_confirm = value;     if (this.valid()) {       console.log('emit' + this.msisdn);       this.emitter.emit(this.msisdn);     }   }    get m1():string {     return this.msisdn;   }   get m2():string {     return this.msisdn_confirm   }    msisdn: string;   msisdn_confirm: string;    constructor() {    }    private valid(): boolean {     if (!/06[0-9]{8}/.test(this.msisdn)) {       this.message = new TranslationPipe().transform("Het mobiele nummer is incorrect, (bijvoorbeeld: 0612345678)")       return false;     } else if (this.msisdn != this.msisdn_confirm) {       this.message = new TranslationPipe().transform("De mobiele nummers komen niet overeen")       return false;     }     this.message = null;     return true;   } } 

So this is a very basic component which validates two strings to be a "valid" dutch Mobile number, so a confirm box so to say. Now I can get my value in the parent component by doing something like

(mobile)="myParam = $event" 

What I want is to use it like

[(mobile)]="myParam" 

This only works for setting though, is this not supported on custom components?

like image 449
Mathijs Segers Avatar asked Jun 16 '16 09:06

Mathijs Segers


People also ask

What is used for two-way data binding in angular2?

Angular's two-way binding syntax is a combination of square brackets and parentheses, [()] . The [()] syntax combines the brackets of property binding, [] , with the parentheses of event binding, () , as follows.

Is angular2 support two-way data binding only?

Angular v2+ supports two-way data binding using ngModel directive and also by having getter and setter methods.

How can you specify two-way binding in Angular?

Two-way data binding can be achieved using a ngModel directive in Angular. The below syntax shows the data binding using (ngModel), which is basically the combination of both the square brackets of property binding and parentheses of the event binding.

Is ngModel necessary for two-way binding?

The Angular uses the ngModel directive to achieve the two-way binding on HTML Form elements. It binds to a form element like input , select , selectarea .


2 Answers

For this compact syntax to work the input and output need to follow specific naming rules

[(mobile)]="myParam" 
  @Output('mobileChange') emitter: EventEmitter<string> = new EventEmitter<string>();   @Input('mobile') set setMobileValue(value) {     this.msisdn_confirm = this.msisdn = value;   } 

Renaming inputs and outputs by passing a string parameter to the decorator is discourages. Rather use

  @Output() mobileChange: EventEmitter<string> = new EventEmitter<string>();   @Input() set mobile(value) {     this.msisdn_confirm = this.msisdn = value;   } 
like image 68
Günter Zöchbauer Avatar answered Oct 13 '22 19:10

Günter Zöchbauer


Another example of Gunter's code above that may help:

export class TaskBook {   public taskBookID: number;   public title: String;  } 

Inside component code:

   ....     <input type="text"  pInputText [(ngModel)]="data!.title" (change)="onDataChange()" />    ....   @Component({   selector: 'taskbook_edit',   templateUrl: './taskbook_edit.component.html'  })     export class TaskbookEditComponent {         @Input() data: TaskBook;       @Output() dataChange = new EventEmitter<TaskBook>();        constructor() { }         onDataChange() {          this.dataChange.emit(this.data);       }       } 

Outside in calling component:

<taskbook_edit  [(data)]="taskbookObj" ></taskbook_edit>   public taskbookObj: TaskBook; 
like image 40
davaus Avatar answered Oct 13 '22 17:10

davaus