我写一个指令,需要一个孤立的范围,但我想绑定到父范围通过
ngModel。
这里的问题是,父的范围值不会改变。@H_502_2@
- <form name="myForm" ng-app="customControl">
- <div ng-init="form.userContent"></div>
- <div contenteditable name="myWidget" ng-model="form.userContent" required>Change me!</div>
- <span ng-show="myForm.myWidget.$error.required">required!</span>
- <hr />
- <textarea ng-model="form.userContent"></textarea>
- </form>
JS@H_502_2@
- angular.module('customControl',[]).directive('contenteditable',function() {
- return {
- restrict : 'A',// only activate on element attribute
- require : '?ngModel',// get a hold of NgModelController
- scope: {},link : function(scope,element,attrs,ngModel) {
- if (!ngModel)
- return; // do nothing if no ng-model
- // Specify how UI should be updated
- ngModel.$render = function() {
- element.html(ngModel.$viewValue || '');
- };
- // Listen for change events to enable binding
- element.bind('blur keyup change',function() {
- scope.$apply(read);
- });
- read(); // initialize
- // Write data to the model
- function read() {
- ngModel.$setViewValue(element.html());
- }
- }
- };
- });
这工作正常,如果我不使用隔离范围的指令@H_502_2@
原因是,由于您为contenteditable指令创建了一个独立的范围,所以同一元素上的ng-model指令也会获得该孤立范围。这意味着您有两个不相互连接的不同作用域,它们都有一个单独更改的form.userContent属性。我想你可以通过这段代码来举例说明:
- <!doctype html>
- <html ng-app="myApp">
- <head>
- <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
- <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
- <script>
- angular.module('myApp',[]).controller('Ctrl',function($scope) {
- })
- .directive('contenteditable',function() {
- return {
- restrict : 'A',// only activate on element attribute
- require : '?ngModel',// get a hold of NgModelController
- scope: {},ngModel) {
- if (!ngModel)
- return; // do nothing if no ng-model
- setInterval(function() {
- if (angular.element('#contenteditable').scope().form)
- console.log(angular.element('#contenteditable').scope().form.userContent);
- if (angular.element('#textarea').scope().form)
- console.log(angular.element('#textarea').scope().form.userContent);
- },1000);
- // Specify how UI should be updated
- ngModel.$render = function() {
- element.html(ngModel.$viewValue || '');
- };
- // Listen for change events to enable binding
- element.bind('blur keyup change',function() {
- scope.$apply(read);
- });
- read(); // initialize
- // Write data to the model
- function read() {
- ngModel.$setViewValue(element.html());
- }
- }
- };
- });
- </script>
- </head>
- <body ng-controller="Ctrl">
- <form name="myForm">
- <div ng-init="form.userContent"></div>
- <div contenteditable name="myWidget" ng-model="form.userContent" id="contenteditable" required>Change me!</div>
- <span ng-show="myForm.myWidget.$error.required">required!</span>
- <hr />
- <textarea ng-model="form.userContent" id="textarea"></textarea>
- </form>
- </body>
- </html>
正如你将在控制台中看到的,有两个不同的范围,如果你改变textarea中的文本,或者改变contenteditable div中的文本,form.userContent会单独改变。@H_502_2@
所以我打赌你在想“足够的解释,并给我一个解决方案!好吧,(对我的知识)没有一个漂亮的解决方案,但有一个工作。您想要做的是将模型的引用引入到您的隔离范围中,并确保它在您的隔离范围中具有与父范围中相同的名称。@H_502_2@
这里是你做的,而不是像这样创建一个空的范围:@H_502_2@
- ...
- scope: {}
- ...
你像这样绑定模型:@H_502_2@
- ...
- scope: {
- model: '=ngModel'
- }
- ....
现在你在你的隔离范围上有一个模型属性,它是对父范围的form.userContent的引用。但ng-model不是在寻找一个模型属性,它正在寻找一个form.userProperty,它仍然不存在于我们孤立的范围。所以要解决这个问题,我们在链接函数中添加:@H_502_2@
- scope.$watch('model',function() {
- scope.$eval(attrs.ngModel + ' = model');
- });
- scope.$watch(attrs.ngModel,function(val) {
- scope.model = val;
- });
第一个监视器将form.userContent的更改同步到我们隔离的form.userContent,第二个监视器确保我们将隔离的form.userContent上的任何更改传播到父作用域。@H_502_2@
我意识到这是一个冗长的答案,也许不是很容易遵循。所以我很乐意澄清你觉得模糊的东西。@H_502_2@