Angular动态追加HTML后ng-model绑定不更新,如何显示值?
你遇到的核心问题是动态添加的HTML没有经过Angular的编译流程——直接用jQuery的append把HTML字符串塞进DOM,Angular根本不知道这些新元素存在,ng-model这类指令完全不会被识别,哪怕你之后给$scope赋值,也没法和输入框建立绑定关系。
推荐方案:用ng-repeat替代手动拼接HTML(Angular最佳实践)
Angular的核心思想之一就是数据驱动视图,与其手动循环拼接HTML,不如把选中的行数据放到一个数组里,用ng-repeat自动生成表单元素,这样Angular会自动编译这些元素,ng-model也能正确绑定。
1. 修改模态框的HTML模板
把.change区域的内容改成ng-repeat结构:
<div class="change"> <!-- 用ng-repeat遍历selectedItems数组,自动生成每一组表单 --> <form name="formChooseAdress_{{$index}}" ng-submit="submitForm($index)" novalidate ng-repeat="item in selectedItems"> <div class="form-group col-md-4 col-lg-4"> <label>Fatura: </label> <input type="text" class="form-control" ng-model="item.chosen" disabled> </div> <div class="form-group col-md-4 col-lg-4"> <label>Valor total: </label> <input type="text" class="form-control" ng-model="item.chosen1" disabled> </div> <div class="form-group col-md-4 col-lg-4"> <label>Valor a pagar: </label> <input type="number" class="form-control" ng-model="item.chosen2" max="item.chosen1" min="0"> </div> <br><br><br><p></p> </form> </div>
2. 简化JavaScript代码
不需要手动拼接HTML,直接把选中的行数据赋值给$scope.selectedItems:
// 获取DataTable中选中的行数据,转成数组 $scope.selectedItems = $('#querytable').DataTable().rows('.selected').data().toArray();
这样ng-repeat会自动遍历selectedItems,每一个item对应选中的一行数据,ng-model直接绑定到item的属性上,输入框会自动显示对应的值,完全不需要手动处理动态变量名。
备选方案:用$compile编译动态添加的HTML(仅当必须手动操作DOM时用)
如果因为业务限制必须手动拼接HTML,那一定要用Angular的$compile服务把HTML编译后再添加到DOM,这样Angular才能识别其中的指令。
修改你的JavaScript代码如下:
var divElement = angular.element(document.querySelector('.change')); var selectedRows = $('#querytable').DataTable().rows('.selected').data(); $scope.dataSelected = []; for(var i = 0; i < selectedRows.length; i++){ $scope.dataSelected.push(selectedRows[i]); // 拼接HTML模板,注意ng-model直接绑定到dataSelected[i]的属性 var formHtml = ` <form name="formChooseAdress" ng-submit="submitForm()" novalidate> <div class="form-group col-md-4 col-lg-4"> <label>Fatura: </label> <input type="text" class="form-control" id="ff_${i}" ng-model="dataSelected[${i}].chosen" disabled> </div> <div class="form-group col-md-4 col-lg-4"> <label>Valor total: </label> <input type="text" class="form-control" id="fs_${i}" ng-model="dataSelected[${i}].chosen1" disabled> </div> <div class="form-group col-md-4 col-lg-4"> <label>Valor a pagar: </label> <input type="number" class="form-control" id="ft_${i}" ng-model="dataSelected[${i}].chosen2" max="dataSelected[${i}].chosen1" min="0"> </div> <br><br><br><p></p> </form> `; // 编译HTML字符串,生成能和$scope绑定的元素 var compiledForm = $compile(formHtml)($scope); // 把编译后的元素添加到目标div divElement.append(compiledForm); };
注意:$compile依赖当前的$scope,编译后的元素会自动和$scope建立绑定,不需要额外调用$scope.$apply()(如果你的代码已经在Angular的上下文里,比如点击事件回调,调用$apply()反而可能抛出错误)。
总结
优先选择ng-repeat方案,它更符合Angular的设计理念,代码更简洁、易维护,也避免了手动操作DOM带来的各种问题。只有在万不得已的情况下,再考虑用$compile处理动态DOM。
内容的提问来源于stack exchange,提问作者capcanaid

