javascript - AngularJS,在指令的独立范围内的嵌入内容中分配与更新范围时不一致

标签 javascript angularjs angularjs-directive angularjs-scope

JSBin 示例: http://jsbin.com/yuyetakonowu/1/edit?html,js,output

摘要: 我有两个指令(myParentDirective 和 myChildDirective)。 myParentDirective 包含 myChildDirective 内容。我正在尝试在 myChildDirective 中双向绑定(bind)模型对象。当我通过简单地更改或添加现有对象实例的属性来“更新”对象时,它会成功工作。但是,当我“分配”一个新对象(使用 Controller 超时函数中的等于运算符)时,myChildDirective 将不会更新。

HTML:

<html ng-app='ValidationApp'>

<head>
    <title>Assigning a model object after isolated scope is set doesn't work</title>
</head>

<body ng-controller='MyController'>

    <h2>MyController.assignedObject: {{assignedObject}}</h2>
    <h2>MyController.updatedObject: {{updatedObject}}</h2>

    <my-parent-directive assigned-object='assignedObject' updated-object='updatedObject'>
        <my-child-directive></my-child-directive>
    </my-parent-directive>


    <script src='//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.js'></script>
    <script src='app.js'></script>
</body>

</html>

JavaScript:

var app = angular.module('ValidationApp', [])

app.controller('MyController', [
    '$scope',
    '$http',
    function($scope, $http) {
        // Model objects loaded on page-load
        $scope.assignedObject = {value: 'pre-update'}
        $scope.updatedObject = {value: 'pre-update'}

        // Mock ajax request
        setTimeout(function() {

            // This is what I'm ultimately trying to accomplish. However, myChildDirective is not properly
            // showing the updated value 'post-update'.
            $scope.assignedObject = {value: "post-update"}

            // I noticed that this line will properly update myChildDirective, but it's not an ideal solution.
            // I'm including it in the example just to show the inconsistent results in myChildDirective.
            $scope.updatedObject.value = "post-update"

            $scope.$apply()

        }, 1000)
    }
])

app.directive('myParentDirective', function() {
    return {
        restrict: 'E',
        transclude: true,
        scope: {
            assignedObject: '=',
            updatedObject: '='
        },
        template: '\
            <h2>myParentDirective.assignedObject: {{assignedObject}}</h2>\
            <h2>myParentDirective.updatedObject: {{updatedObject}}</h2>\
            <div ng-transclude></div>\
            ',
        controller: function($scope, $element) {
            this.assignedObject = $scope.assignedObject
            this.updatedObject = $scope.updatedObject
        }
    }
})

app.directive('myChildDirective', function() {
    return {
        restrict: 'E',
        require: '^myParentDirective',
        scope: false,
        template: '\
            <h2>myChildDirective.myParentDirective.assignedObject: {{myParentDirective.assignedObject}}</h2>\
            <h2>myChildDirective.myParentDirective.updatedObject: {{myParentDirective.updatedObject}}</h2>\
            ',
        link: function($scope, $element, $attrs, myParentDirective) {
            $scope.myParentDirective = myParentDirective
        }
    }
})

最佳答案

我找到了一些解决问题的方法...

问题是我在 myParentDirective 中将 $scope.signedObject 分配给 this.signedObject。当我这样做时, myChildDirective 无法知道属性何时发生更改。通常,将调用 $scope.$apply() 函数来通知所有观察者范围属性已更改,但由于我将此对象引用重新分配给 this.assignedObject myChildDirective 永远不会收到该事件。

最简单的解决方案可以在这里找到:http://jsbin.com/yuyetakonowu/11/edit 。基本上,这只是继承父作用域,以便我可以依靠 Angular 的作用域来发出适当的事件并相应地更新 myChildDirective。

但是,这对我来说还不够好,因为我还需要 myChildDirective 拥有一个具有自己属性的隔离范围。这意味着我不能简单地“继承”父作用域。我已通过以下方法解决了此问题:http://jsbin.com/yuyetakonowu/9/edit .

最终结果:

HTML:

<html ng-app='ValidationApp'>

<head>
    <title>Assigning a model object after isolated scope is set doesn't work</title>
</head>

<body ng-controller='MyController'>

    <h1>MyController</h1>
    <h2>assignedObject: {{assignedObject}}</h2>
    <h2>updatedObject: {{updatedObject}}</h2>

    <my-parent-directive assigned-object='assignedObject' updated-object='updatedObject'>
        <my-child-directive child-property='child-property-value'></my-child-directive>
    </my-parent-directive>


    <script src='//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.js'></script>
    <script src='app.js'></script>
</body>

</html>

JavaScript:

var app = angular.module('ValidationApp', [])

app.controller('MyController', [
    '$scope',
    '$http',
    function($scope, $http) {
        // Model objects loaded on page-load
        $scope.assignedObject = {value: 'pre-update'}
        $scope.updatedObject = {value: 'pre-update'}

        // Mock ajax request
        setTimeout(function() {

            // This is what I'm ultimately trying to accomplish. However, myChildDirective is not properly
            // showing the updated value 'post-update'.
            $scope.assignedObject = {value: "post-update"}

            // I noticed that this line will properly update myChildDirective, but it's not an ideal solution.
            // I'm including it in the example just to show the inconsistent results in myChildDirective.
            $scope.updatedObject.value = "post-update"

            $scope.$apply()

        }, 1000)
    }
])

app.directive('myParentDirective', function() {
    return {
        restrict: 'E',
        transclude: true,
        scope: {
            assignedObject: '=',
            updatedObject: '='
        },
        template: '\
            <h1>myParentDirective</h1>\
            <h2>assignedObject: {{assignedObject}}</h2>\
            <h2>updatedObject: {{updatedObject}}</h2>\
            <div ng-transclude></div>\
            ',
        controller: function($scope, $element) {
            // Generally, exposing isolate scope is considered bad practice. However, this directive is intended
            // to be used with child directives which explicitly depend on this directive. In addition, child
            // directives will likely need their own isolated scope with two-way binding of properties on this scope.
            this._scope = $scope
        }
    }
})

app.directive('myChildDirective', function() {
    return {
        restrict: 'E',
        require: '^myParentDirective',
        scope: {
            childProperty: '@'
        },
        template: '\
            <h1>myChildDirective</h1>\
            <h2>childProperty: {{childProperty}}</h2>\
            <h2>assignedObject: {{assignedObject}}</h2>\
            <h2>updatedObject: {{updatedObject}}</h2>\
            ',
        link: function($scope, $element, $attrs, myParentDirective) {
            myParentDirective._scope.$watch('assignedObject', function(newValue, oldValue) {
                $scope.assignedObject = newValue
            })
            myParentDirective._scope.$watch('updatedObject', function(newValue, oldValue) {
                $scope.updatedObject = newValue
            })
        }
    }
})

关于javascript - AngularJS,在指令的独立范围内的嵌入内容中分配与更新范围时不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25676488/

相关文章:

javascript - 在浏览器中使用 axios 处理重定向

angularjs - Protractor 等待数据库连接

AngularJS指令: Are we not supposed to use the suffix "start"?

javascript - 如何使用 angularJs 打印数字表?

javascript - 指令的竞争条件

javascript - 使用 Javascript 或 Jquery 完全隐藏框架集中的框架

javascript - 将对象值从字符串转换为普通值(它是原始数据类型)

javascript - 获取请求失败,错误为 : connect ECONNREFUSED

javascript - AngularJS:一次显示数组中的一个特定对象

javascript - 使用 angular-google-maps 指令与异步加载的 <markers> 不起作用