【问题标题】:AngularJS : Change parent scope value from custom directiveAngularJS:从自定义指令更改父范围值
【发布时间】:2015-07-13 20:39:18
【问题描述】:

由于某种原因,我无法根据我在 SO 上看到的其他示例来完成这项工作。

这是我的指令:

(function () {

    angular.module('materialDesign')
        .directive('aSwitch', directive);

    function directive() {

        return {
            templateUrl: 'elements/material/switch/switch.html',
            transclude: false, // I've tried true here
            restrict: 'E',
            scope: {
                enabled: '=',
                toggleState: '=',
            },
            link: function(scope, element) {
                element.on('click touchstart', function() {
                    scope.toggleState = !scope.toggleState;
                });
            }
        };
    }
})();

以及在切换开关/复选框时我想要更改的控制器范围值:

$scope.hideInactive = true;

html:

<a-switch toggle-state="hideInactive"></a-switch>

在我的 html 页面的更下方,我有这个:

<div ng-show="!hideInactive">
    <!-- stuff -->
</div>

编辑:

这个版本“现在可以工作”,但是当我第二次点击我的开关/复选框时,element.on 会触发两次,这会将我的范围值翻转回原来的值.....基本上,它是不要让我“取消选中”我的切换。

angular.module('material')
    .directive('aSwitch', [
        '$timeout', function($timeout) {
            return {
                templateUrl: 'elements/material/switch/switch.html',
                transclude: false,
                restrict: 'E',
                scope: {
                    enabled: '=',
                    toggleState: '=',
                },
                link: function (scope, element) {
                    element.on('click touchstart', function () {
                        $timeout(function () {
                            scope.toggleState.state = !scope.toggleState.state;
                            scope.$apply();
                        });
                    });

                }
            };
        }
    ]);

编辑和最终解决方案:

这是修复了所有问题的更新后的指令链接属性。我想补充一点,还使用了 Oleg Yudovich 的答案(将对象作为属性而不是 true/false 本身传递)

link: function (scope, element) {
                element.on('click touchstart', function (event) {
                    if (event.srcElement && event.srcElement.id && event.srcElement.id === "switch") {
                        event.stopPropagation();

                        $timeout(function() {
                            scope.toggleState.state = !scope.toggleState.state;
                        });
                    }
                });
            }

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    尝试像这样传递对象而不是原始变量:

    $scope.hideInactive = {
       state: false;
    }
    

    html 没有变化:

    <a-switch toggle-state="hideInactive"></a-switch>
    

    在你的指令中:

    scope.toggleState.state = !scope.toggleState.state;
    

    Reed 这篇很棒的文章:https://github.com/angular/angular.js/wiki/Understanding-Scopes

    【讨论】:

    • 请查看我的更新(添加了额外的 html 部分)。我仍在努力让它发挥作用。 (并且还在阅读您的链接文章)
    • 这里没有改变只是一个模型而不是变量:
    【解决方案2】:

    你需要在作用域改变后运行摘要循环,因为从事件改变作用域绑定不会运行角度摘要循环,你需要通过scope.$apply()手动运行它

    指令

    (function () {
    
        angular.module('materialDesign')
            .directive('aSwitch', directive);
    
        function directive($timeout) {
    
            return {
                templateUrl: 'elements/material/switch/switch.html',
                transclude: false, // I've tried true here
                restrict: 'E',
                scope: {
                    enabled: '=',
                    toggleState: '=',
                },
                link: function(scope, element) {
                    element.on('click touchstart', function() {
                      $timeout(function(){
                        scope.toggleState = !scope.toggleState;
                      });
                    });
                }
            };
        }
    })();
    

    【讨论】:

    • 我读过专门调用摘要循环是不好的,我不能将 element.on 部分包装在 $timeout 中吗?
    • @ganders 使用 $timeout 会更安全......因为它不会与当前正在运行的摘要周期冲突......请参阅我的更新
    • 我在 element.on 周围添加了超时(没有范围。$apply),它开始工作......等待两分钟后。现在我将在 element.on 中尝试它。
    • @ganders 那是我的错..代码没有正确更新..你不应该指定任何超时时间..更新的代码肯定会工作
    • 它不会与当前运行的摘要循环冲突 - 浏览器触发 DOM 事件时不能有运行循环。
    【解决方案3】:

    试试下面的代码:

    angular.module('material').directive('aSwitch', ['$timeout', function($timeout) {
        return {
            templateUrl: 'elements/material/switch/switch.html',
            transclude: false,
            restrict: 'E',
            scope: {
                enabled: '=',
                toggleState: '=',
            },
            link: function(scope, element) {
                element.on('click touchstart', function() {
                    $timeout(function() {
                        scope.toggleState.state = !scope.toggleState.state;
                        scope.$apply();
                    });
                });
            }
        };
    }]);
    

    【讨论】:

    • $timeout 将在摘要循环完成时触发 $apply。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    相关资源
    最近更新 更多