gpt4 book ai didi

angularjs - 为什么 ngModel.$setViewValue(...) 不起作用

转载 作者:行者123 更新时间:2023-12-03 09:21:36 28 4
gpt4 key购买 nike

我正在编写一个需要隔离作用域的指令,但我想通过 ngModel 将它绑定(bind)到父作用域.

这里的问题是父级的范围值没有改变。

标记

<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());
}
}
};
});

演示: Fiddle .

如果我不为指令使用隔离范围,这很好用

演示: Fiddle .

最佳答案

原因是因为您正在为您的 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 div 中的文本,它们会单独更改。

所以我敢打赌你在想“解释够了,给我一个解决方案!”。好吧,(据我所知)没有一个很好的解决方案,但是有一个有效的解决方案。您要做的是将模型的引用引入您的隔离范围,并确保它在您的隔离范围中与父范围中的名称相同。

这是您所做的,而不是像这样创建一个空范围:
...
scope: {}
...

你像这样绑定(bind)模型:
...
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;
});

第一个 watch 同步更改 form.userContent来自我们对我们孤立的 form.userContent 的指令之外的内容,第二个监视确保我们在隔离的 form.userContent 上传播任何更改直到父范围。

我意识到这是一个冗长的答案,也许不太容易理解。因此,我很乐意澄清您认为模糊的任何内容。

关于angularjs - 为什么 ngModel.$setViewValue(...) 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15269737/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com