Ответ 1
Причина в том, что, поскольку вы создаете изолированную область для своей директивы 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
на них изменяются отдельно, если вы меняете текст в текстовом поле или если вы меняете текст в своем contenteditable div.
Итак, держу пари, что вы думаете "достаточно с объяснением и покажите мне решение!". Что ж, я не знаю (насколько мне известно) довольно подходящее решение, но есть одно, что работает. То, что вы хотите сделать, это привести ссылку модели в вашу изолированную область и убедиться, что она имеет то же имя в вашей изолированной области действия, что и в родительской области.
Вот что вы делаете, вместо того, чтобы создавать пустую область вроде этого:
...
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
до родительской области.
Я понимаю, что это длинный ответ, и, возможно, не очень легко следовать. Поэтому я был бы рад очистить все, что, по вашему мнению, расплывчато.