Angular - @Input的双向数据绑定无法正常工作

时间:2018-02-15 10:32:37

标签: angular typescript data-binding components interaction

我尝试通过将其余部分重置为0来实现仅接受数值的自定义输入,使用以下代码作为输入组件:

import {Component, Input, Output, ElementRef, EventEmitter} from '@angular/core';
import {Observable} from 'rxjs/Rx';

@Component({
    selector: 'debounce-input',
    template: '<input type="text" [placeholder]="placeholder" [(ngModel)]="_v">'
})
export class DebounceInputComponent {
    @Input() placeholder: string
    @Input() delay: number = 300

    _v: string

    @Input()
    get v(): string {
        return this._v
    }

    set v(_value) {
        this._v = _value
        this.valueChange.emit(this.v)
    }

    @Output() valueChange: EventEmitter<any> = new EventEmitter<any>()

    @Output() value: EventEmitter<any> = new EventEmitter<any>()

    constructor(private elementRef: ElementRef) {
        const eventStream = Observable.fromEvent(elementRef.nativeElement, 'keyup')
            .map(() => this.v)
            .debounceTime(this.delay)
            .distinctUntilChanged()
        eventStream.subscribe((obj) => this.value.emit({v: this.v}))
    }
}

使用以下代码在AppComponent中导入上述组件:

  1. HTML部分:

    <div style="text-align:center">
      <debounce-input [v]="mynumber"
      delay="1000"
      placeholder="Type something..."
      (value)="handle($event)">
      </debounce-input>
    </div>
    
  2. TypeScript部分:

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
      title = 'app';
    
      mynumber = 0
    
      handle(obj) {
        console.log(obj.v)
        if (isNaN(Number(obj.v))) {
          console.log('trying to reset invalid input to 0')
          this.mynumber = 0
        }
      }}
    
  3. 问题是每当我输入一个非数字值时,AppComponent无法将输入重置为0,尽管&#34;尝试将无效输入重置为0&#34;消息显示在控制台中。

    这种行为的原因是什么?

2 个答案:

答案 0 :(得分:1)

我明白了。您的@Input值未更改,因为父级中的mynumber未更改子级更改。我添加了这个功能,它起作用了:

handle(obj) {
    console.log(obj.v)
    if (isNaN(Number(obj.v))) {
      console.log('trying to reset invalid input to 0')
      this.mynumber = 0;
    } else {
      this.mynumber = obj.v; // add this line
    }
  }

P.S。 不过,我仍然会考虑将您的输入限制为仅限数字类型,并添加一些过滤器以防止设置“0123”等数字。

答案 1 :(得分:0)

修改输入组件中的setter,并使ngModel指向v而不是_v。

  import {Component, Input, Output, ElementRef, EventEmitter} from '@angular/core';
  import {Observable} from 'rxjs/Rx';

  @Component({
      selector: 'debounce-input',
      template: '<input type="text" [placeholder]="placeholder" [(ngModel)]="v">'
  })
  export class DebounceInputComponent {
      @Input() placeholder: string
      @Input() delay: number = 300

      _v: string

      @Input()
      get v(): string {
          return this._v
      }

      set v(_value) {
        if (isNaN(Number(_value))) {
          console.log('trying to reset invalid input to 0')
          this._v = '0';
          return;
        }
          this._v = _value
          this.valueChange.emit(this.v)
      }

      @Output() valueChange: EventEmitter<any> = new EventEmitter<any>()

      @Output() value: EventEmitter<any> = new EventEmitter<any>()

      constructor(private elementRef: ElementRef) {
          const eventStream = Observable.fromEvent(elementRef.nativeElement, 'keyup')
              .map(() => this.v)
              .debounceTime(this.delay)
              .distinctUntilChanged()
          eventStream.subscribe((obj) => this.value.emit({v: this.v}))
      }
  }