AngularJS 单击输入字段一段时间后模型更改时视图未更新

AngularJS view not updating while model changed changed after clicking input fields for some time

我制作了一个 json 用于生成 PDF 的文件设计器。

如果您想查看整个代码,请打开底部的插件 link。

视图未按预期运行。在调试器中,当我在其 SVG 场景中拖动元素时,模型会立即发生变化。 输入没有改变。 但是,如果我在输入框之间单击,它会突然将视图更新为正确的值。

这是我在指令内的范围变量中设置值的地方:

    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>

这是预览 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">

它稍后更新输入字段的事实清楚地表明数据已正确传输到控制器。为什么右边的Form更新的这么懒。 他们没有办法强制视图重新渲染吗?

提前非常感谢您提供的每条有用建议:/

https://plnkr.co/edit/UwbxV6eQ7YBWEtZAFkCj?p=preview

您可以使用 $scope.$apply()

强制渲染视图

$apply() is used to execute an expression in AngularJS from outside of the AngularJS framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). Because we are calling into the AngularJS framework we need to perform proper scope life cycle of exception handling, executing watches.

https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$申请

还有一个$applyAsyc()方法:

Schedule the invocation of $apply to occur at a later time. The actual time difference varies across browsers, but is typically around ~10 milliseconds. This can be used to queue up multiple expressions which need to be evaluated in the same digest.

https://docs.angularjs.org/api/ng/type/$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 执行变化。