简体   繁体   English

具有隔离范围的角度双向绑定似乎是单向的

[英]angular two-way bind with isolate scope appears to be one-way

I have written a simple click-to-edit directive using an isolate scope so that it's reusable. 我使用隔离范围编写了一个简单的单击以编辑指令,以便可重复使用。 When I use it, the source value ( '=' ) in the controller scope is never updated, though its original value is applied within the directive. 当我使用它时,控制器作用域中的源值('=')永远不会更新,尽管它的原始值应用于指令中。 It's as if the binding is one-way ( '@' ). 好像绑定是单向('@')。

Here's the code: 这是代码:

app.directive("ngClickToEdit", function() {
    return {
        template:
            '<div>' +
                '<div ng-show="enabled">' +
                    '<input ng-change="validator()" ng-blur="enabled=false"  ng-model="source"/>' +
                '</div>' +
                    '<div ng-show="!enabled" ng-bind="source" ng-click="enable()"></div>' +
            '</div>',
        restrict: "E",
        replace: true,
        scope: {
            validator: '&',
            source: '=',
        },
        link: function(scope, element) {
            scope.enabled = false;

            var input = element.children()[0].firstChild;

            scope.enable = function() {
                scope.enabled = true;
                setTimeout(function() {
                    input.focus();
                    input.select();
                }, 200);
            };
        },
    };
});

Here is an invocation in the controller (edited to wrap in ng-if div block): 这是控制器中的调用(编辑后包装在ng-if div块中):

<div ng-if='name'>
    <ng-click-to-edit validator='validateName()' source='name' />
</div>

When validateName() in the controller scope is invoked the value of 'name' is the original value and not the (changed) value in the directive's input control. 在控制器作用域中调用validateName()时,“名称”的值是原始值,而不是指令的输入控件中的(更改)值。 The model is not updated. 模型未更新。 Why? 为什么?

Resolved : The ng-if block creates a child scope, passing name as a string primitive due to prototypal inheritance . 解决 :ng-if块创建一个子范围,由于原型继承 ,将name作为字符串基元传递。 Passing an object reference into the directive solves the problem. 将对象引用传递到指令可以解决该问题。 See a revised plunker here. 请在此处查看修订的插件

This is because outer scope's name has not yet been assigned the inner scope's source . 这是因为尚未为外部作用域的name分配内部作用域的source When you declare an isolate scope with "=" , Angular $watch es for changes (see code ) in both values and does the two-way binding, but the $watches haven't yet fired when validator is invoked. 当您使用"="声明隔离范围时,Angular $watch用于两个值的更改(请参见代码 ),并进行双向绑定,但是调用validator程序时,还没有触发$ watches。

You can check it with this code: 您可以使用以下代码进行检查:

$scope.validateName = function(){
  console.log("outside directive: name = " + $scope.name);

  $timeout(function(){
    console.log("but just after digest cycle: name = " + $scope.name);
  });
};

There are a few things you could do: 您可以做一些事情:

1) You could fire validator after $timeout : 1)您可以在$timeout之后触发验证器:

scope.localValidate = function(){
   $timeout(function(){ scope.validator(); });
};

and the template: 和模板:

<input ng-change="localValidate()"..>

2) You could $watch for changes in source and then fire the $validator (instead of in ng-change ): 2)您可以$ watch监视source更改,然后触发$validator (而不是ng-change ):

scope.$watch("source", function(){
    scope.validator();
});

3) You could pass the value to validate into the validator function: 3)您可以将值传递给验证器函数:

<input ng-change="validator({name: source})"..>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM