Angular JS指令隔离范围双向绑定无法正常工作

时间:2015-09-29 08:46:17

标签: javascript angularjs directive

我知道这是一个非常常见的问题,但我搜索了很多帖子,并没有找到解决问题的方法。

我的指令的目的是响应性地最小化侧栏。 为了做到这一点,我注册媒体查询并添加监听器以添加特定的类,但我有一个问题,isMinimized上的双向绑定不会更新父范围。

实际上,它会在首次调用_mqlMinimizeListener(mql***Devices);_mqlUnminimizeListener(mql***Devices);时初始化时更新父作用域(以检测屏幕的初始大小),但在值不再更新之后。

这是我的指示:

angular.module('app.minimizableSideBar').directive('minimizableSideBar',
[
    '$window',
    function($window) {
        return {
            restrict: 'A',
            scope: {
                minimizeOn: '@',
                addClass: '@',
                isMinimized: '='
            },
            link: function(scope, element) {

                /**
                 * Initialize the directive and handle behavior regarding provided params
                 */
                var init = function() {

                    if (!_validParams()) {
                        return;
                    }

                    // If browser is recent
                    if ($window.matchMedia) {
                        if (scope.minimizeOn === 'object') {
                            _handleRangeBreakpoint();
                        } else {
                            scope.minimizeOn = parseInt(scope.minimizeOn);
                            _handleSimpleBreakpoint();
                        }
                    } else {
                        // If browser outdated, we fall back on innerWidth
                        scope.$watch(function() {
                            return $window.innerWidth;
                        }, function(value) {
                            if (value < scope.minimizeOn) {
                                element.addClass(scope.addClass);
                            } else {
                                element.removeClass(scope.addClass);
                            }
                        });
                    }

                    // We handle external minimization (i.e. the user want to minimize/un-minimize
                    // the sidebar by clicking on a button
                    scope.$watch('isMinimized', function(value) {
                        if (value) {
                            element.addClass(scope.addClass);
                        } else {
                            element.removeClass(scope.addClass);
                        }
                    });
                };

                /**
                 * Check params validity
                 *
                 * @returns {Boolean} true if params are valid, false otherwise
                 * @private
                 */
                var _validParams = function() {
                    if (scope.addClass &&
                        scope.minimizeOn) {

                        if (scope.minimizeOn === 'object' &&
                            (!scope.minimizeOn.lowerSize ||
                            !scope.minimizeOn.upperSize ||
                            Number.isNaN(scope.minimizeOn.lowerSize) ||
                            Number.isNaN(scope.minimizeOn.upperSize))) {
                            return false;
                        } else if (Number.isNaN(scope.minimizeOn)) {
                            return false;
                        }
                        return true;
                    }
                };

                /**
                 * Listener for minimizing action
                 *
                 * @param {MediaQueryList} mql a media query listener
                 */
                var _mqlMinimizeListener = function(mql) {
                    if (mql.matches) {
                        element.addClass(scope.addClass);
                        scope.isMinimized = true;
                    }
                };

                /**
                 * Listener for unminimizing action
                 *
                 * @param {MediaQueryList} mql a media query listener
                 */
                var _mqlUnminimizeListener = function(mql) {
                    if (mql.matches) {
                        element.removeClass(scope.addClass);
                        scope.isMinimized = false;
                    }
                };

                /**
                 * Handle Range breakpoint with lower size and higher size
                 *
                 * @private
                 */
                var _handleRangeBreakpoint = function() {
                    var lowerSize = parseInt(scope.minimizeOn.lowerSize);
                    var upperSize = parseInt(scope.minimizeOn.upperSize);

                    // Handle screen sizes
                    //-- In the range
                    var mqlRangeDevices = $window.matchMedia('screen and (min-width: ' + lowerSize + ' px) and (max-width: ' + upperSize + 'px)');
                    mqlRangeDevices.addListener(_mqlMinimizeListener);
                    _mqlMinimizeListener(mqlRangeDevices);

                    //-- Out of the range
                    var mqlInfDevices = $window.matchMedia('screen and (max-width: ' + lowerSize - 1 + 'px)');
                    mqlInfDevices.addListener(_mqlUnminimizeListener);
                    _mqlUnminimizeListener(mqlInfDevices);

                    var mqlSupDevices = $window.matchMedia('screen and (min-width: ' + (upperSize + 1) + 'px)');
                    mqlSupDevices.addListener(_mqlUnminimizeListener);
                    _mqlUnminimizeListener(mqlSupDevices);
                };

                /**
                 * Handle simple breakpoint (i.e. when mnimizeOn only contains string for one size)
                 *
                 * @private
                 */
                var _handleSimpleBreakpoint = function() {
                    var mqlInfDevices = $window.matchMedia('screen and (max-width: ' + scope.minimizeOn + 'px)');
                    mqlInfDevices.addListener(_mqlMinimizeListener);
                    _mqlMinimizeListener(mqlInfDevices);

                    var mqlSupDevices = $window.matchMedia('screen and (min-width: ' + (scope.minimizeOn + 1) + 'px)');
                    mqlSupDevices.addListener(_mqlUnminimizeListener);
                    _mqlUnminimizeListener(mqlSupDevices);
                };

                init();
            }
        };
    }
]
);

这是HTML标记:

<div class="sidebar navbar-collapse collapse sidebar-navbar-collapse"
     data-minimizable-side-bar
     data-minimize-on="992"
     data-add-class="sidebar-minimized"
     data-is-minimized="sidebar.isMinimized">
</div>

谢谢!

1 个答案:

答案 0 :(得分:1)

好的我终于理解了我的错误!

我正在更新&#34; native&#34; Javascript监听器,我必须调用范围。$ apply()来更新范围。