Angular 2 + ngrx / store:单向绑定到<input />

时间:2016-09-25 04:45:00

标签: angular ngrx

[ngModel]上通过<input>使用单向绑定时,在输入中输入字符始终会在<input>的值中添加字符。问题是,如果[ngModel]表达式继续返回其现有值,则不会刷新<input>值。

这是一个简单的例子:

@Component({
  selector: 'my-component',
  template: `
    <input type="text" [ngModel]="foo.bar" />
  `
})
export class MyComponent {
  private foo = {
    bar: 'baz'
  };
}

我希望输入始终显示&#34; baz&#34;无论用户输入如何,但事实并非如此。

我正在寻找这种行为的原因是针对ngrx / store / redux应用程序,其中<input>的值应由单向流动的状态确定。我创建了example use case on Plunker,其中Misko Hevery的描述不应该是可编辑的。模型确实没有变化,但<input>显示用户输入的内容。

在&#34; No trackBy&#34;部分,它正常工作,但只是因为Angular正在重绘所有强制重新评估的DOM元素(但这不是一个解决方案)。将disabledreadonly属性添加到<input>对我来说是不可接受的答案,因为组件应该不知道不允许更改此字段的潜在复杂状态逻辑。

我在React Redux中看到过这种行为,如果我们无法阻止用户改变他们自己的视图,我想知道如何在Angular 2中使用单向绑定。

3 个答案:

答案 0 :(得分:1)

因为当从状态返回的值相同时不会触发ChangeDetection,所以唯一直接的方法是通过从组件构造函数中的商店的customer.descriptionLocked属性绑定到customerDescriptionLocked属性集。我知道你不希望组件只使用readonly,因为你不希望组件知道状态确定锁的逻辑。通过绑定到customerDescriptionLocked属性,组件仍然不知道状态的设置逻辑。

<input type="text" placeholder="Description" [ngModel]="record.customerDescription" 
[readonly]="record.customerDescriptionLocked" (ngModelChange)="updateDescription(record, $event)" />

组件构造函数:

constructor(public store: Store<AppState>, private ref: ChangeDetectorRef){
  this.customerState = store.select('customer');
  this.customerState.subscribe((customerState:CustomerState) => {
    this.dashboardRecords = customerState.customers.map((customer:Customer):DashboardRecord => {
      return {
        customerId: customer.id,
        customerName: `${customer.personalInfo.firstName} ${customer.personalInfo.lastName}`,
        customerDescription: customer.description,
        customerDescriptionLocked: customer.descriptionLocked,
        customerUpdateCount: customer.updated
      };
    })
  });
}

答案 1 :(得分:0)

@Component({
  selector: 'my-component',
  template: `
    <input type="text" [value]="foo.bar" />
//[ngModel] is for two way binding
  `
})
export class MyComponent {
  private foo = {
    bar: 'baz'
  };
}

答案 2 :(得分:0)

@Component({
  selector: 'my-component',
  template: `
    <input type="text" [value]="foo.bar" (keydown) = "$event.preventDefault();"/>
//add preventDefault() to keydown event to prevent user from changing the value shown in input field
  `
})
export class MyComponent {
  private foo = {
    bar: 'baz'
  };
}