angularjs – 为什么是ngModel $setViewValue(…)不工作

前端之家收集整理的这篇文章主要介绍了angularjs – 为什么是ngModel $setViewValue(…)不工作前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我写一个指令,需要一个孤立的范围,但我想绑定到父范围通过 ngModel

这里的问题是,父的范围值不会改变。@H_502_2@

标记@H_502_2@

  1. <form name="myForm" ng-app="customControl">
  2. <div ng-init="form.userContent"></div>
  3. <div contenteditable name="myWidget" ng-model="form.userContent" required>Change me!</div>
  4. <span ng-show="myForm.myWidget.$error.required">required!</span>
  5. <hr />
  6. <textarea ng-model="form.userContent"></textarea>
  7. </form>

JS@H_502_2@

  1. angular.module('customControl',[]).directive('contenteditable',function() {
  2. return {
  3. restrict : 'A',// only activate on element attribute
  4. require : '?ngModel',// get a hold of NgModelController
  5. scope: {},link : function(scope,element,attrs,ngModel) {
  6. if (!ngModel)
  7. return; // do nothing if no ng-model
  8.  
  9. // Specify how UI should be updated
  10. ngModel.$render = function() {
  11. element.html(ngModel.$viewValue || '');
  12. };
  13.  
  14. // Listen for change events to enable binding
  15. element.bind('blur keyup change',function() {
  16. scope.$apply(read);
  17. });
  18. read(); // initialize
  19.  
  20. // Write data to the model
  21. function read() {
  22. ngModel.$setViewValue(element.html());
  23. }
  24. }
  25. };
  26. });

演示:Fiddle。@H_502_2@

这工作正常,如果我不使用隔离范围的指令@H_502_2@

演示:Fiddle。@H_502_2@

原因是,由于您为contenteditable指令创建了一个独立的范围,所以同一元素上的ng-model指令也会获得该孤立范围。这意味着您有两个不相互连接的不同作用域,它们都有一个单独更改的form.userContent属性。我想你可以通过这段代码来举例说明:
  1. <!doctype html>
  2. <html ng-app="myApp">
  3. <head>
  4. <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
  5. <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
  6. <script>
  7. angular.module('myApp',[]).controller('Ctrl',function($scope) {
  8.  
  9. })
  10. .directive('contenteditable',function() {
  11. return {
  12. restrict : 'A',// only activate on element attribute
  13. require : '?ngModel',// get a hold of NgModelController
  14. scope: {},ngModel) {
  15. if (!ngModel)
  16. return; // do nothing if no ng-model
  17.  
  18. setInterval(function() {
  19. if (angular.element('#contenteditable').scope().form)
  20. console.log(angular.element('#contenteditable').scope().form.userContent);
  21.  
  22. if (angular.element('#textarea').scope().form)
  23. console.log(angular.element('#textarea').scope().form.userContent);
  24. },1000);
  25.  
  26. // Specify how UI should be updated
  27. ngModel.$render = function() {
  28. element.html(ngModel.$viewValue || '');
  29. };
  30.  
  31. // Listen for change events to enable binding
  32. element.bind('blur keyup change',function() {
  33. scope.$apply(read);
  34. });
  35. read(); // initialize
  36.  
  37. // Write data to the model
  38. function read() {
  39. ngModel.$setViewValue(element.html());
  40. }
  41. }
  42. };
  43. });
  44. </script>
  45. </head>
  46. <body ng-controller="Ctrl">
  47. <form name="myForm">
  48. <div ng-init="form.userContent"></div>
  49. <div contenteditable name="myWidget" ng-model="form.userContent" id="contenteditable" required>Change me!</div>
  50. <span ng-show="myForm.myWidget.$error.required">required!</span>
  51. <hr />
  52. <textarea ng-model="form.userContent" id="textarea"></textarea>
  53. </form>
  54. </body>
  55. </html>

正如你将在控制台中看到的,有两个不同的范围,如果你改变textarea中的文本,或者改变contenteditable div中的文本,form.userContent会单独改变。@H_502_2@

所以我打赌你在想“足够的解释,并给我一个解决方案!好吧,(对我的知识)没有一个漂亮的解决方案,但有一个工作。您想要做的是将模型的引用引入到您的隔离范围中,并确保它在您的隔离范围中具有与父范围中相同的名称。@H_502_2@

这里是你做的,而不是像这样创建一个空的范围:@H_502_2@

  1. ...
  2. scope: {}
  3. ...

你像这样绑定模型:@H_502_2@

  1. ...
  2. scope: {
  3. model: '=ngModel'
  4. }
  5. ....

现在你在你的隔离范围上有一个模型属性,它是对父范围的form.userContent的引用。但ng-model不是在寻找一个模型属性,它正在寻找一个form.userProperty,它仍然不存在于我们孤立的范围。所以要解决这个问题,我们在链接函数添加:@H_502_2@

  1. scope.$watch('model',function() {
  2. scope.$eval(attrs.ngModel + ' = model');
  3. });
  4.  
  5. scope.$watch(attrs.ngModel,function(val) {
  6. scope.model = val;
  7. });

第一个监视器将form.userContent的更改同步到我们隔离的form.userContent,第二个监视器确保我们将隔离的form.userContent上的任何更改传播到父作用域。@H_502_2@

我意识到这是一个冗长的答案,也许不是很容易遵循。所以我很乐意澄清你觉得模糊的东西。@H_502_2@

猜你在找的Angularjs相关文章