我写这需要一个孤立的作用域的指示,但我想将其绑定到通过父范围ngModel 。
这里的问题是,父母的范围值没有得到改变。
标记
<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
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());
}
}
};
});
演示: 小提琴 。
如果我不使用分离范围的指令也能正常工作
演示: 小提琴 。
其原因是因为你创建一个孤立的范围内为您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: {},
link : function(scope, element, attrs, 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>
正如你将在你的控制台中看到,有两个不同的范围和form.userContent
他们分开,如果你在textarea的修改文本或更改,如果您更改CONTENTEDITABLE格中的文本。
所以,我敢打赌,你会想“足以与解释,并告诉我一个解决方案!”。 那么,有没有(据我所知)这一个漂亮的解决方案,但有一个工程。 你想要做的就是把模型的参考到您的隔离范围,并确保它在你的孤立范围相同的名称,在父范围。
这里是你做什么,而不是创建一个空的范围是这样的:
...
scope: {}
...
您绑定这样的模式:
...
scope: {
model: '=ngModel'
}
....
现在你有一个model
上的孤立范围属性,它是一个参考form.userContent
上你的父母范围。 但是ng-model
是不是找一个model
属性,它在寻找一个form.userProperty
仍然没有在我们的孤立范围存在。 因此,要解决这个问题,我们我们的逻辑函数里面添加这个:
scope.$watch('model', function() {
scope.$eval(attrs.ngModel + ' = model');
});
scope.$watch(attrs.ngModel, function(val) {
scope.model = val;
});
第一块手表同步的变化form.userContent
是来自于我们的指令以外的我们孤立form.userContent
,而第二块手表可以确保我们传播我们的孤立的任何更改form.userContent
到父范围。
我知道这是一个漫长的答案,也许不是很容易。 所以,我很乐意clearify什么,你的感觉是模糊的。
第一个答案解释了这个问题很好,我相信我有避免额外的手表一个简单的解决方案。
总结答案1. ngModel不能分离范围内工作,因为你预期它的元素绑定到不在其范围。 他们是在父范围。
解决方案1,绑定到父母的财产
<div contenteditable name="myWidget" ng-model="form.userContent" required>Change me!</div>
变
<div contenteditable name="myWidget" ng-model="$parent.form.userContent" required>Change me!</div>
溶液2,移动ngModel分离物范围以外的
require : '?ngModel',
变成require : '?^ngModel',
在^告诉你的指令在ngModel父元素看
<div contenteditable name="myWidget" ng-model="form.userContent" required>Change me!</div>
变
<div ng-model="form.userContent">
<div contenteditable name="myWidget" required>Change me!</div>
</div>
我不知道这是否会为你工作。 然而,你可以试试看。
HTML:
<form name="myForm" ng-app="customControl">
<div ng-init="form.userContent"></div>
<div contenteditable name="myWidget" ng-model="form" required>Change me!</div>
<span ng-show="myForm.myWidget.$error.required">Required!</span>
<hr />
<textarea ng-model="form.content"></textarea>
</form>
JS
angular.module('customControl', []).directive('contenteditable', function() {
return {
restrict : 'A', // only activate on element attribute
require : '?ngModel', // get a hold of NgModelController
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({'content': element.html()});
}
}
};
});