简体   繁体   English

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

[英]Angular 2 + ngrx/store: one-way binding to an <input>

When using one-way binding via [ngModel] on an <input> , typing characters into the input always adds characters to the <input> 's value. <input>上通过[ngModel]使用单向绑定时,在<input>键入字符总是会在<input>的值中添加字符。 The problem is that if the [ngModel] expression continues to return its existing value, the <input> value is not refreshed. 问题是如果[ngModel]表达式继续返回其现有值,则不会刷新<input>值。

Here is a simple example: 这是一个简单的例子:

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

I would expect the input to always show "baz" regardless of user input, but this is not the case. 我希望无论用户输入如何,输入总是显示“baz”,但事实并非如此。

The reason I am looking for this behavior is for an ngrx/store / redux application, where an <input> 's value should be determined by state flowing one-way. 我正在寻找这种行为的原因是ngrx / store / redux应用程序,其中<input>的值应该由单向流动的状态决定。 I've created an example use case on Plunker , where Misko Hevery's description should not be editable. 在Plunker上创建了一个示例用例 ,其中Misko Hevery的描述不应该是可编辑的。 The model is indeed unchanged, but the <input> shows whatever the user types. 模型确实没有改变,但<input>显示用户<input>内容。

In the "No trackBy" section, it works correctly, but only because Angular is redrawing all of the DOM elements which forces a proper re-evaluation (but this is not a solution). 在“No trackBy”部分,它可以正常工作,但只是因为Angular正在重绘所有强制重新评估的DOM元素(但这不是解决方案)。 Adding disabled or readonly attributes to the <input> is not an acceptable answer for me since the component should be unaware of the potentially complex state logic that disallows changes to this field. disabledreadonly属性添加到<input>对我来说不是一个可接受的答案,因为组件应该不知道不允许更改此字段的潜在复杂状态逻辑。

I've seen this behavior in React Redux, and I'm wondering how we can use one-way binding in Angular 2 if we cannot stop the user from mutating their own view. 我在React Redux中看到过这种行为,我想知道如果我们无法阻止用户改变他们自己的视图,我们如何在Angular 2中使用单向绑定。

Because ChangeDetection won't trigger when the value returned from the state is the same, the only straight-forward way to do this is by binding to a customerDescriptionLocked property set from the store's customer.descriptionLocked property in the component's constructor. 因为当从状态返回的值相同时不会触发ChangeDetection,所以唯一直接的方法是通过绑定到组件构造函数中商店的customer.descriptionLocked属性的customerDescriptionLocked属性集。 I know you didn't want the component to use readonly because you didn't want the component to be aware of the state's logic for determining the lock. 我知道你不希望组件只使用readonly,因为你不希望组件知道状态确定锁的逻辑。 By binding to the customerDescriptionLocked property, the component is still unaware of the state's logic for setting it. 通过绑定到customerDescriptionLocked属性,组件仍然不知道状态的设置逻辑。

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

The component constructor: 组件构造函数:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM