2015-09-29 2 views
1

Я знаю, что это довольно распространенная проблема, но я искал много сообщений и не нашел решения моей проблемы.Угловая директива JS изолированная область двусторонняя привязка не работает

Целью моей директивы является минимизация боковой панели. Для этого я регистрирую медиа-запросы и добавляю к нему слушателей для добавления определенного класса, но у меня есть проблема с двусторонней привязкой в ​​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

Хорошо, я наконец понял свою ошибку!

Поскольку я обновляю область видимости от «родных» слушателей Javascript, я должен вызвать область действия. $ Apply(), чтобы получить область обновления.

Смежные вопросы