Javascript AngularJS视图未更新,而模型在单击输入字段一段时间后发生更改
我制作了一个用于生成PDF的json文件设计器 如果您想看到整个代码的运行,请打开底部的plunker链接 视图的行为与预期不符。在调试器中,当我在SVG场景中拖动元素时,模型会立即更改。 但是输入没有改变。 但是,如果我在输入框之间单击,它会突然将视图更新为正确的值 这是我在指令中设置scope变量值的地方:Javascript AngularJS视图未更新,而模型在单击输入字段一段时间后发生更改,javascript,angularjs,svg,angularjs-directive,ngdraggable,Javascript,Angularjs,Svg,Angularjs Directive,Ngdraggable,我制作了一个用于生成PDF的json文件设计器 如果您想看到整个代码的运行,请打开底部的plunker链接 视图的行为与预期不符。在调试器中,当我在SVG场景中拖动元素时,模型会立即更改。 但是输入没有改变。 但是,如果我在输入框之间单击,它会突然将视图更新为正确的值 这是我在指令中设置scope变量值的地方: function endDrag(evt) { if (selectedElement) { let selectedEntry = sc
function endDrag(evt) {
if (selectedElement) {
let selectedEntry = scope.data.templateData.find(function(entry) {
return entry.name === selectedElement.getAttribute("data-entry-name");
});
if(selectedEntry){
selectedEntry.x = parseInt(selectedElement.transform.baseVal.getItem(0).matrix.e / scope.data.pdfViwer.zoom);
selectedEntry.y = parseInt(selectedElement.transform.baseVal.getItem(0).matrix.f / scope.data.pdfViwer.zoom);
}
selectedElement = null;
}
}
这是控制器中的我的数据对象:
$scope.data = {
name: "",
type: [{name:'Text',value:'text'}, {name:'Image',value:'image'}, {name:'Line',value:'line'}],
templateData: [{
'type': {name:'Text',value:'text'},
'name': 'test',
'text': 'test3',
'x': 100,
'y': 100
}],
pdfViwer: {
height: 2970,
width: 2000,
zoom: .3
},
output: {
show:true
}
}
这些是更新太晚的输入字段:
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">(X,Y)</span>
</div>
<input type="text" ng-model="entry.x" aria-label="x" ng-init="entry.x=data.pdfViwer.width / 2" class="form-control">
<input type="text" ng-model="entry.y" aria-label="y" ng-init="entry.y=data.pdfViwer.height / 2" class="form-control">
</div>
(X,Y)
这是预览svg中svg组的组标记:
<g ng-repeat="entry in getTemplateData()" class="draggable" data-entry-name="{{entry.name}}"
transform="translate({{entry.x * data.pdfViwer.zoom}} {{entry.y * data.pdfViwer.zoom}})"
draggable="true">
它在稍后更新输入字段的事实清楚地表明,数据已正确地传输到控制器。为什么右边的表单更新得这么慢。
难道他们没有办法强迫视图重播吗
提前非常感谢您提供的每一个有用的建议:/
您可以强制视图使用
$scope.$apply()
$apply()用于从AngularJS框架外部执行AngularJS中的表达式。(例如,来自浏览器DOM事件、setTimeout、XHR或第三方库)。因为我们正在调用AngularJS框架,所以我们需要执行异常处理、执行监视的适当范围生命周期
$rootScope.Scope#$apply
还有一个$applyAsyc()
方法:
将$apply的调用安排在以后进行。实际时差因浏览器而异,但通常约为10毫秒。
这可用于将需要在同一摘要中计算的多个表达式排队
$rootScope.Scope#$applyAsync
我玩了你的plnker,它看起来像是如果你把scope.$apply()
在endDrag()
函数的末尾,它将按预期工作:
function endDrag(evt) {
if (selectedElement) {
let selectedEntry = scope.data.templateData.find(function(entry) {
return entry.name === selectedElement.getAttribute("data-entry-name");
});
if(selectedEntry){
selectedEntry.x = parseInt(selectedElement.transform.baseVal.getItem(0).matrix.e / scope.data.pdfViwer.zoom);
selectedEntry.y = parseInt(selectedElement.transform.baseVal.getItem(0).matrix.f / scope.data.pdfViwer.zoom);
}
selectedElement = null;
}
scope.$apply();
}
这样做的原因是,您的拖动事件似乎与Angular的摘要周期没有关联,因此您需要手动调用它,Angular才能对更改进行操作。我仍然不熟悉$scope。$apply和$digest,但您的示例让它更清楚。感谢您基本上,您在网格中单击的事件处理程序发生在Angular的知识范围之外,因此您需要手动调用scope.$apply(),以便它使用最新更新重新呈现模型。此外,这也是为什么(之前)当您单击输入框时它会更新,因为此时您正在触发角度更新,并且它会跟上对模型所做的更改。当您在角度范围内执行某些操作时,例如使用ng模型,这会自动发生。