【问题标题】:reset AngularJS Material Design custom component to pristine将 AngularJS Material Design 自定义组件重置为原始
【发布时间】:2018-03-09 01:22:20
【问题描述】:

我有一个 AngularJS 自定义组件,它基本上围绕 Material Design mdSelect,但通过其绑定提供了对可用值、默认值和当前值的简单配置。

但该组件在mdDialog 中用作通用编辑组件,可以根据正在编辑的内容更改其选项。因此,有一个“下一步”按钮可以转到下一个要编辑的“事物”。当按下按钮时,自定义组件将具有新的可用值、默认值和当前值——如下所示:

<foo-component default-value="dialog.getDefaultFoo()" current-foo="dialog.currentFoo">
</foo-component>

请注意,如果未给出可用值列表(如上例所示),则该组件会假定一个值列表中只有一个值,即“默认值”。

所以当用户选择“下一步”时,mdSelect 中的值列表会发生变化,因为dialog.getDefaultFoo() 返回的值。新选择的值将是dialog.currentFoo

但如果dialog.currentFoonull,我希望控件自动选择指定的默认值,或者如果没有指定默认值,则选择第一个可用值。当使用$onInit 创建组件时,这很容易。但是一旦创建,我怎么知道(在组件内部)用户选择了“下一步”并且可用值列表发生了变化?

在“下一步”按钮的代码中,我调用this.fooForm.$setPristine()。根据documentation,当调用此方法时,表单控制器将“传播到此表单中包含的所有控件”。所以我考虑让我的自定义控件钩子检测到正在调用$setPristine(),这样如果新值是null,它就可以从列表中自动选择一个默认值。但是现在我又回到了同样的情况:我的自定义组件如何检测到表单上正在调用$setPristine()

本质上,我的自定义组件需要检测其绑定值之一何时发生变化,并在某些条件下对其他值执行一些自定义更新。我知道我可以使用自定义组件外部的getter/setter,但是自定义组件如何检测到它的绑定值之一发生了变化?

为了让事情变得更复杂,dialog.currentFoo 实际上是一个函数,我的组件将其识别为 getter/setter 函数,它将根据对话框的状态返回/更新正确的值。所以我什至无法检测到这个值已经改变,因为实际的函数永远不会改变——只有它返回的值会改变。

实际上比这更复杂,因为mdSelect 只是发送到dialog.currentFoo 的对象的一个​​片段;否则它不会传播到组件之外。

想总结一下,我需要在自定义组件中知道绑定dialog.currentFoo(它实际上是一个 getter/setter 方法)现在是否会返回 null,以便自定义组件可以选择默认值(也是动态的) ) 基于内部mdSelect 中列出的当前项目(也是动态的)。我会接受解决方法,例如检测到 $setPristine() 已在封闭表单上调用。我什至会接受 hack,例如当某些外部状态发生变化时,强制 AngularJS 重新创建自定义组件。

【问题讨论】:

  • Plunker 或/和一些代码在这里真的会有所帮助。有一些想法,但不确定我是否正确

标签: angularjs angularjs-directive


【解决方案1】:

这很棘手,因为 AngularJS 很棘手,而且跟踪自定义 AngularJS 控件/输入组件的信息非常困难。

首先需要做的是make the custom component use the normal ngModel framework;尝试使用双向绑定 currentValue 来“伪造”它并不会因为这种复杂性而减少它,此外,ngModel 是 AngularJS 的“正确”方式。要实现这一点,您需要使用NgModelController。尽管one page 给出了神奇的公式,但找出如何使用组件执行此操作本身就很困难。它是这样的:

require: {
  ngModelCtrl: "ngModel"
},
bindings: {
  ngModel: "<"
  //TODO add defaultValue or whatever other properties here
},

那你不直接访问二元值;你使用NgModelController接口:

//get the current value
const foo = this.ngModelCtrl.$modelValue;
//set the current value
this.ngModelCtrl.$setViewValue(foo);

据我所知,如果您将 ng-model-options="{getterSetter:true}" 添加到组件中,ngModelOptions 将自动应用于您的模型,并且会自动调用 getter/setter。

现在您已被整个ngModel 框架所吸引,并使用NgModelController 添加/访问验证器和各种高级功能。

回到我的需求,在某些情况下我需要“重置组件”,我可以修补到NgModelController#$setPristine()。表单控制器识别出我的组件是ngModel 框架的一部分,并在表单重置为原始状态时调用$setPristine()

  this.$onInit = () => {

    this.ngModelCtrl.$setPristine = () => {
      myInternalValue1 = null;
      myInternalValue2 = this.defaultValue;
    };

    this.ngModelCtrl.$setPristine(); //initialize default value
  };

这解释了我对表单控制器“传播[ing $setPristine()] 到此表单中包含的所有控件”的疑问,我在最初的问题中提到了这一点。秘诀在于,组件必须成为真正的ngModel 系统的一部分,这样它才能按照 AngularJS 的预期进行交互,并能够访问重要的内部方法。

【讨论】:

    猜你喜欢
    • 2018-02-19
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-21
    • 1970-01-01
    相关资源
    最近更新 更多