为什么ngModel。$ setViewValue(...)没有工作 [英] Why is ngModel.$setViewValue(...) not working from

查看:111
本文介绍了为什么ngModel。$ setViewValue(...)没有工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在写这需要一个孤立的作用域的指令,但我想通过的 ngModel

I'm writing an directive which needs an isolated scope, but I want to bind it to the parent scope via ngModel.

下面的问题是,家长的范围值没有得到改变。

Here the problem is that the parent's scope value is not getting changed.

标记

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

演示:小提琴

此,如果我不使用分离的范围的指令正常工作

This works fine if I don't use a isolated scope for the directive

演示:小提琴

推荐答案

的原因是,因为你创造了你的 CONTENTEDITABLE 指令一个孤立的范围, NG-模型在相同的元素指令获取隔离的范围为好。这意味着你有没有相互连接两个不同的领域,它们都具有单独更改了 form.userContent 属性。我想你可以通过这个code例证是:

The reason is that since you're creating an isolated scope for your contenteditable directive, the ng-model directive on the same element gets that isolated scope as well. Which means that you have two different scopes that aren't connected to each other, which both have a form.userContent property that changes separately. I guess you could exemplify it by this code:

<!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。

As you'll see in your console, there are two different scopes and form.userContent on them change separately if you change the text in the textarea or if you change the text in your contenteditable div.

所以,我敢打赌,你在想足以与解释,并告诉我一个解决方案!。那么,有没有(据我所知)这一个pretty的解决方案,但有一个工程。你想要做的就是把模型的参考到您的隔离范围,并确保它在你孤立的范围相同的名称在父范围。

So I bet you're thinking "enough with the explaining and show me a solution!". Well, there aren't (to my knowledge) a pretty solution for this, but there is one that works. What you want to do is bring a reference of the model into your isolated scope, and make sure that it has the same name in your isolated scope as in the parent scope.

下面是你做什么,而不是像这样创建一个空的范围:

Here's what you do, instead of creating an empty scope like this:

...
scope: {}
...

您绑定的模式是这样的:

You bind the model like this:

...
scope: {
    model: '=ngModel'
}
....

现在你有你的孤立范围模式属性,是你的父母 form.userContent 参考范围。但 NG-模型是不是找一个模式属性,它在寻找一个形式.userProperty 仍然没有在我们的孤立范围存在。因此,要解决这个问题,我们我们的联函数内部补充一点:

Now you have a model property on your isolated scope that is a reference to form.userContent on your parent scope. But ng-model isn't looking for a model property, it's looking for a form.userProperty which still doesn't exist in our isolated scope. So to fix this, we add this inside our linking function:

scope.$watch('model', function() {
    scope.$eval(attrs.ngModel + ' = model');
});

scope.$watch(attrs.ngModel, function(val) {
    scope.model = val;
});

第一块手表上同步 form.userContent 来自我们的指令对我们的孤立 form.userContent 和第二块手表可以确保我们宣传我们的隔离 form.userContent 到父范围。

The first watch syncs changes on form.userContent that comes from outside of our directive to our isolated form.userContent, and the second watch makes sure that we propagate any changes on our isolated form.userContent up to the parent scope.

我知道这是一个漫长的答案,也许不是很容易。所以,我很乐意clearify什么,你的感觉是模糊的。

I realize that this is a lengthy answer, and perhaps not very easy to follow. So I'd be happy to clearify anything that you feel is blurry.

这篇关于为什么ngModel。$ setViewValue(...)没有工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆