Angular - 来自@Input的双向数据绑定不起作用

Posted

技术标签:

【中文标题】Angular - 来自@Input的双向数据绑定不起作用【英文标题】:Angular - two way data binding from @Input not working 【发布时间】:2018-07-26 01:56:23 【问题描述】:

我正在尝试实现一个只接受数值的自定义输入,方法是将其余部分重置为 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 中导入的:

    html 部分:

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

    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
        
      
    

问题是每当我输入非数字值时,AppComponent 无法将输入重置为 0,尽管控制台中会显示“尝试将无效输入重置为 0”消息。

这种行为的原因是什么?

【问题讨论】:

console.log(obj.v) 的值是多少?你尝试过 obj.target.value 吗? @Niladri 这与我在输入组件中键入的任何值相同。 你认为你可以设置一个堆栈闪电战让我们玩你的代码吗? @BorisLobanov 我尝试这样做,但 stackblitz 未能检测到我添加的组件。 问题解释令人困惑的问题是什么?您想将输入字段的用户限制为type="number" 还是说type="text" 【参考方案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
    
  

附: 但是,我仍然会考虑将您的输入仅限于数字类型并添加一些过滤器以防止设置像“0123”这样的数字。

【讨论】:

我更新了你提到的代码,但我仍然遇到同样的问题 - 输入“a”后输入没有重置为 0。 stackblitz.com/edit/angular-kscfaw 为我工作。看看,也许你缺少什么? 我不明白 我认为是延迟导致了问题。如果你输入 1,再给它一秒钟,然后输入 'a' 就可以正常工作了【参考方案2】:

修改输入组件中的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))
      
  

【讨论】:

以上是关于Angular - 来自@Input的双向数据绑定不起作用的主要内容,如果未能解决你的问题,请参考以下文章

带有@input属性的Angular 7双向绑定

React中双向数据绑定基本原理

angular 双向数据绑定number类型的变量怎么让它没有默认值

Angular 2复选框双向数据绑定

v-mode 双向数据绑定

typescript 双向数据绑定。 (*注意:为了能够使用'ngModel',需要将formsModule(来自@ angular / forms)添加到您的imports []数组