AngularJS 1.4:使用 $compile 插入列表时选择列表值未正确初始化

Posted

技术标签:

【中文标题】AngularJS 1.4:使用 $compile 插入列表时选择列表值未正确初始化【英文标题】:AngularJS 1.4: Select List Value not Initializing Correctly when List is Inserted with $compile 【发布时间】:2015-08-15 11:13:48 【问题描述】:

这里有一些快速的背景信息。我刚刚升级到 Angular 1.4。我正在使用用 C# 编写的 API 进行服务器端调用。

我页面的一部分显示了 2 个选择列表(项目和子项目)。两者都应该默认为“(Select a ______)”,我将其列为每个选择的第一个选项,“值”为 0。适当的 ng-model 变量初始化为 0。

选择列表的实际 html 代码是在服务器端使用字符串连接生成的,通过 $http 传递给客户端,并使用调用 $compile 的指令插入(一点都不理想,但我的客户端有把我锁在这个 API 上)。在 1.4 更新之前,一切都运行良好。

现在,我的项目选择列表默认为空。当我检查元素时,这就是我所看到的......

<select ng-change="updateSubProjList()" ng-model="curProjID">
    <option value="? number:0 ?"></option>
    <option value="0">(Select a Project)</option>
    <option value="1">First Project</option>
    <option value="2">Second Project</option>
    ...
</select>

...用第一个 "? number:0 ?"条目是当前选择的条目。我的子项目选择列表仍然初始化得很好,这让这更加奇怪。

我知道在 AngularJS 1.4 的更新中对 $compile 进行了一些更新,但我无法找到解决问题的方法。任何帮助将不胜感激。

【问题讨论】:

curProjID的值是多少? 控制器加载时初始化为0。 【参考方案1】:
<select ng-model="x">
   <option value="100">100</option>
   <option value="200">200</option>
</select>

scope.x = '200'

或阅读此文档。 https://docs.angularjs.org/guide/migration

【讨论】:

【参考方案2】:

还有另一种方法:使用指令实现解析器和格式化程序。见http://plnkr.co/edit/JZPay8jgm5AXKGXDCjSb

感谢 narretz!

伪代码:

<select convert-number ng-model="x">
   <option value="100">100</option>
   <option value="200">200</option>
</select>


app.directive('convertNumber', function() 
  return 
    require: 'ngModel',
    link: function(scope, el, attr, ctrl) 
      ctrl.$parsers.push(function(value) 
        return parseInt(value, 10);
      );

      ctrl.$formatters.push(function(value) 
        return value.toString();
      );      
    
  
);

【讨论】:

太棒了。谢谢。这是一个绝妙的答案。【参考方案3】:

我有同样的问题。我没有确保我的 javascript 代码在所有地方都使用字符串,而是执行了以下操作:

从 HTML 文件中删除了 &lt;option ...&gt;

在 JavaScript 中引入了一个列表,类似于:

var orderQuantities = [
         id: 100, text: '100' ,
         id: 200, text: '200' ,
         id: 300, text: '300' ,
];

确保 orderQuantities 在范围内可见

select标签中使用ng-option如下:

<select ng-model="vm.entity.OrderQuantity" ng-options="orderQuantity.id as orderQuantity.text for orderQuantity in vm.orderQuantities"></select>

【讨论】:

通过这种方法,vm.entity.OrderQuantity 内部绑定了什么?是只有 id(即 100、200、300)还是整个选定对象(例如 id: 200, text: '200' )?【参考方案4】:

通过比较&lt;option value="0"&gt; 中的value 属性,在 1.4 中似乎发生了与所选选项如何匹配 ngModel 的更改 - 它现在需要显式使用字符串进行匹配,而不是允许一个整数。

事实上,documentation 明确指出:

在没有ngOptions 的情况下使用的select 指令的值始终是一个字符串。当模型需要绑定到非字符串值时,您必须使用指令显式转换它...或使用ngOptions 指定选项集。

要修复,将$scope.curProjID的初始化值更改为字符串:

$scope.curProjID = "0"; // 而不是 $scope.curProjID = 0;

当没有匹配项时(也没有,除非您分配字符串"0"),select 添加一个“未知”选项:&lt;option value="? number:0 ?"&gt;&lt;/option&gt;

【讨论】:

这完全正确。谢谢!对于任何想知道的人,我的第二个选择语句有效,因为选项来自使用“ng-options”加载的对象数组,而不是巨大的串联字符串。 作为一个快速修复,我刚刚更改了我的 ng-model 绑定以包含“toString()” @ jeremychild,这是一个“快速休息”...它可能适用于匹配,但它不会在选择变化时更新模型($scope.reason),这是整体目的ng-model 干得好,Angular!看完这个答案后我的脸就像:O.

以上是关于AngularJS 1.4:使用 $compile 插入列表时选择列表值未正确初始化的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS:使用 $compile 将 html 附加到网页

AngularJS:在包含带有 templateurl 的指令的 html 上使用 $compile

Angularjs:错误:[$compile:ctreq] 控制器“carousel”,指令“ngTransclude”需要,找不到

angularjs指令中的compile详解

AngularJS指令中的compile与link函数解析

Angularjs+Typescript 指令实现 $compile