【问题标题】:angularjs ng-model doesn't updateangularjs ng-model 不更新
【发布时间】:2016-10-17 16:31:59
【问题描述】:

我有一个 Font Awesome 图标选择器,我将它用于我的应用程序,这样员工就可以轻松访问不同的图标,而无需在线搜索代码。

现在当我点击一个图标时,它不会更新 ng-model。我首先必须为 AngularJS 输入另一个字符或空格来识别输入中所做的更改。

https://i.gyazo.com/21d80e370726166a200f1165e169a0cf.gif,这是正在发生的事情的例子。

如您所见,在左下角,我制作了一个标签,显示同一 ng-model 中的数据。现在,当我选择一个图标时,模型不会更新。只有在我输入一个空格或另一个字符后它才会更新。

我的代码:

editCellTemplate: function (container, options) {
    container.html('<input class="icon-picker-input edit icp icp-auto" type="text" ng-model="iconInput" /><script>$(".icp-auto").iconpicker();</script>');
    options.setValue($scope.iconInput);
    $compile(container)($scope);
}

我正在使用来自 DevExtreme 的网格视图和自定义 editCellTemplate

绑定:

这里声明:

有人知道如何解决这个问题吗?提前致谢!

【问题讨论】:

  • 能否添加相关代码?
  • @DeblatonJean-Philippe 我已经添加了一些代码,应该足以理解发生了什么。
  • 这是用于网格中每个单元格的模板,对吧?请分享iconpicker()的代码。并在底部显示您用于标签的绑定。
  • @CobusKruger 这个模板确实用于网格中的每个单元格。 iconpicker() 是一个库:github.com/mjolnic/fontawesome-iconpicker,我将添加到问题中。

标签: javascript angularjs typescript font-awesome devextreme


【解决方案1】:

您的代码未按预期工作的主要原因是 Angular 仅监视用户交互事件以更新模型。您的图标选择器通过直接在输入中设置值来完全绕过 Angular。

为了更新模型,您需要在图标选择器更新过程中设置hook:每当您选择图标时,要么自己覆盖iconInput范围变量(并将其包装在$scope.$apply调用中)或者更简单地说,触发输入元素上的'input' 事件,这将导致 Angular 获取新值(参见here)。

我建议你这样做:

editCellTemplate: function (container, options) {
    container.html('<input class="icon-picker-input edit icp icp-auto" type="text" ng-model="iconInput" />');
    options.setValue($scope.iconInput);        
    $compile(container)($scope);

    // Avoid inline script tags, you can make the iconpicker here
    $(".icp-auto").iconpicker();

    // Watch for icon picker selections
    $(".icp-auto").on('iconpickerSelected', function(e) {
        // Fire the "input changed" event
        $(e.currentTarget).trigger('input');
    });
}

请注意,我删除了编译后的 html 中的脚本标签,因为您可以在主代码中完美地实例化图标选择器。脚本标签在全局上下文中进行评估,这通常不是您想要的。

更新:您在评论中报告的编译时错误是由于您的 Typescript 设置具有 JQuery 类的定义(可能是 jquery.d.ts 文件),其中不包括iconPicker() 方法。在运行时,在 Angular 中编译的 &lt;script&gt; 标签的内容被直接解释为纯 Javascript,避免了 Typescript 的类型检查。

请参阅this answer,了解在 JQuery 接口上启用其他方法的简单方法。我强烈建议您停止将逻辑放入已编译的 &lt;script&gt; 元素中,它很有可能会回来咬您。

【讨论】:

  • 首先,当我尝试用 JQuery 加载它时,我收到了这个错误:gyazo.com/82326d20be3b8f655c010907a8c3157a, &gt;&gt; Scripts/App/intranet/controllers/manageintranetcontroller.ts(31,48): error TS2339: Property 'iconpicker' does not exist on type 'JQuery'.
  • 好吧,我忽略了你使用 Typescript 的事实。要解决该编译时错误,您需要在 JQuery 类型上定义 iconpicker 方法。但为了让你的东西正常工作,只需在脚本标签中插入 iconpicker() 回调即可。
  • 它现在确实工作得更好了,它会立即更新 ng-model。谢谢,仍然有一点麻烦..但这是一大步。谢谢!
  • @Peurr 不客气,稍后我会更新我的答案以说明 Typescript 的微妙之处。
【解决方案2】:

您的问题是 iconpicker() 更新 input 没有 Angular 注意到。解决这个问题的方法是直接调用$scope.$apply()。这里的问题是您包含脚本的奇怪方式。 jQuery 语法只会调用 iconpicker() 来匹配第一个元素,所以我认为如果你在演示中编辑第二行,它根本不会起作用。

相反,生成一个数字 id 并更改为:

editCellTemplate: function (container, options) {
    container.html('<input class="icon-picker-input edit icp icp-auto"' +
      ' type="text" ng-model="iconInput" id="uniqueID"/>' +
      '<script>$("#uniqueID").iconpicker();$scope.$apply();</script>');
    options.setValue($scope.iconInput);
    $compile(container)($scope);
}

...其中 uniqueID 显然是唯一 ID。我将把它作为练习留给读者。

【讨论】:

  • 添加 ID 和 $scope.apply(); 后,我收到此错误::10966/#/intranet:1 Uncaught ReferenceError: $scope is not defined现在的代码: editCellTemplate: function (container, options) { container.html('&lt;input class="icon-picker-input edit icp icp-auto" type="text" ng-model="iconInput" id="iconPicker" /&gt;&lt;script&gt;$("#iconPicker").iconpicker();$scope.$apply();&lt;/script&gt;'); options.setValue($scope.iconInput); $compile(container)($scope); }
  • 这行不通。 $scope.$apply 需要在每次更新时调用。
  • @Peurr 是的,这是您附加脚本的方式的问题。正确的方法是将其附加到定义 $scope 的控制器中。 Amine 的回答有效地做到了这一点,然后进行了 $apply 调用。这是一个很好的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
  • 2019-06-02
相关资源
最近更新 更多