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

27,137

Solution 1

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;
  }

Solution 2

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;
Share:
27,137
Mathijs Segers
Author by

Mathijs Segers

Currently employed as Frontend developer. Background in Mobile, Backend, Frontend with various languages and frameworks.

Updated on August 07, 2022

Comments

  • Mathijs Segers
    Mathijs Segers over 1 year

    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?