【问题标题】:Angular 2 + ngrx/store: one-way binding to an <input>Angular 2 + ngrx/store:单向绑定到 <input>
【发布时间】:2018-04-24 23:06:27
【问题描述】:

当在&lt;input&gt; 上通过[ngModel] 使用单向绑定时,在输入中输入字符总是会将字符添加到&lt;input&gt; 的值中。问题是如果[ngModel] 表达式继续返回其现有值,&lt;input&gt; 值不会刷新。

这是一个简单的例子:

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

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

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

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

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

【问题讨论】:

  • 你找到解决办法了吗?
  • 已经在 github (github.com/ngrx/store/issues/228) 上看到过这个问题的讨论,但是超时解决方案对我来说似乎很臭。您找到其他解决方案了吗?

标签: angular ngrx


【解决方案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
      };
    })
  });
}

【讨论】:

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

    【讨论】:

    • 将输入字段的“[value]”属性与您想要的任何内容绑定。更改输入字段不会影响变量的实际值。让我知道这是否有帮助。
    • 您提到“[ngModel] 用于双向绑定”,但它与使用[value] 具有完全相同的单向效果,这意味着更改输入字段不会影响使用任一属性的变量/模型。它也有完全相同的问题,即输入的值与模型不一致,所以这对我没有帮助。请尝试the plunker,如果您有其他想法,请告诉我。谢谢!
    【解决方案3】:
    @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'
      };
    }
    

    【讨论】:

    • 这确实会阻止用户的键将其变为输入值,但不幸的是,它也阻止了 (ngModelChange)(change) 触发,因此我无法将新值传播到减速器。
    猜你喜欢
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    • 2017-03-29
    • 1970-01-01
    相关资源
    最近更新 更多