2016-07-04 116 views
2

我正嘗試創建一個下拉菜單的自定義指令。
這是我的代碼:https://plnkr.co/edit/YqJ6tz4fwvBRmtmzeCJr當另一個打開時不會關閉angularjs下拉菜單

要關閉下拉列表,我檢查該指令元素之外的單擊事件。

$document.bind('click', function() { 
    scope.closeDropdown(); 
    }); 

但這個代碼的問題是當一個下拉列表打開,另一個是單擊第一個不關閉。

如何關閉另一個點擊時的下拉菜單? 我可以通過在控制器中聲明一個變量來做到這一點,並在打開下拉列表前每次檢查一次。但是這種方式不能單獨使用。

任何幫助?

回答

1

可以使用納克級的添加類 '節目',這使得顯示器塊

更新後的模板

<div class="selector"> 
<div class="box-container"> 
    <input type="text" class="search search-input" placeholder="{{dname}}" isDropDownInput="true" ng-model="userInput" /> 
    <ul class="dropdown-list" ng-class="{show:showDropDown}"> 
    <li ng-repeat="value in data | filter:userInput track by $index"> 
     <span > 
      <input class="check-select" type="checkbox" value="{{value}}" ng-click="toggleCheck(value)" isdropdown="true" ng-checked="isChecked(value)"/> 
      {{value }} 
     </span> 
    </li> 
    </ul> 
</div> 
</div> 

用於切換當用戶點擊窗口對象的類使用控制器,這裏是更新後的腳本,

(function(){ 
'use strict'; 

angular.module('app') 
// safeApply service, courtesy Alex Vanston and Andrew Reutter 
.factory('safeApply', [function ($rootScope) { 
    return function ($scope, fn) { 
    var phase = $scope.$root.$$phase; 
    if (phase == '$apply' || phase == '$digest') { 
     if (fn) { 
      $scope.$eval(fn); 
     } 
    } else { 
     if (fn) { 
      $scope.$apply(fn); 
     } else { 
      $scope.$apply(); 
     } 
    } 
} 
}]) 
.directive('dropDown', dropDown); 

function dropDown($document) { 
    var directive = { 
     restrict: 'EA', 
     replace: true, 
     scope: { 
      dname: '@', 
      data: '=', 
      selected : '=choices', 
     }, 
     templateUrl: 'template.html', 
     link: linker, 
     controller: dropdownController 
    }; 
    return directive; 

    function dropdownController($scope, $rootScope, $window, safeApply){ 

    $window.onclick = function(event){ 
     console.log("event target = " + event.target.attributes); 
     if(event.target.attributes && event.target.attributes.isDropDownInput){ 
      $rootScope.$broadcast("closeAllDropDown", {'isDropDownInput':true, 'inputId':event.target.attributes.placeHolder.nodeValue}) 
     } 
     else if(event.target.attributes && !event.target.attributes.isDropDown){ 
      $rootScope.$broadcast("closeAllDropDown", {'isDropDownInput':false}) 
     } 
     }; 

     $scope.$on("closeAllDropDown", function(event,payload){ 
     console.log("eventObj = " + event, payload.isDropDownInput); 
     if(payload.isDropDownInput){ 
      if(event.currentScope.dname == payload.inputId){ 
      event.currentScope.showDropDown = true; 
      } 
      else{ 
      event.currentScope.showDropDown = false; 
      } 
     } 
     else{ 
      $scope.showDropDown = false; 
     } 
     safeApply($scope); 
     console.log('$scope.showDropDown = ' + $scope.showDropDown) 
     }); 

     $scope.openDropDown = function() { 

     $scope.showDropDown = true; 
     }; 


     $scope.closeDropdown = function() { 
      $scope.showDropDown = false; 
     }; 
     $scope.toggleCheck = function(item){ 
     $scope.showDropDown = true; 
      if($scope.multiSelect){ 
       $scope.multiChoice(item); 
      }else{ 
       $scope.singleChoice(item); 
      } 
     }; 

     $scope.isChecked = function (item) { 
      if ($scope.selected.indexOf(item) !== -1) { 
       return true; 
      } 
      return false; 
     }; 

     $scope.singleChoice = function(item) { 
      $scope.selected.length = 0; 
      $scope.selected.push(item); 
     }; 

     $scope.multiChoice = function (item) { 
      var index = $scope.selected.indexOf(item); 

      if(index > -1){ 
       $scope.selected.splice(index, 1); 
      }else { 
       $scope.selected.push(item); 
      } 
     }; 

     $scope.removeItem = function(item){ 
      $scope.selected.splice($scope.selected.indexOf(item), 1);   
     }; 
    } 

    function linker(scope, elem, attr) { 
     console.log('dropdown::loaded'); 
     scope.showDropDown = false; 
     scope.selected = []; 

     scope.multiSelect = 'multiselect' in attr; 


    } 
    } 
dropDown.$inject = ['$document']; 
})(); 

希望它能幫助,而不是使用jQuery

+0

非常感謝這個解決方案...完美的工作。我認爲使用ng-show會比ng-class更好。 –

+0

但是,此解決方案存在一個問題,當您單擊它時,下拉菜單會關閉。你能解決這個問題嗎? –

+0

希望更新後的代碼可以正常工作。在廣播事件時,我們可以通過在複選框上添加一個屬性來忽略複選框點擊,也可以在摘要循環未進行時使用由Van Vanston和Andrew Reutter提供的工廠安全地調用apply()來啓動摘要循環 –

2

一種方式來做到這一點是:

scope.toggleCheck = function(item,element){ 
       scope.closeDropdown(); 
       if(scope.multiSelect){ 
        scope.multiChoice(item); 
       }else{ 
        scope.singleChoice(item); 
       } 
      }; 

或者更好的辦法:

scope.openDropDown = function() { 
       $('.dropdown-list').css('display','none'); 
       elem.find('.dropdown-list').css('display','block'); 
      }; 

https://plnkr.co/edit/zwTjiktY8H3HmHnvQnoa?p=preview

+0

感謝...這是工作: ) –

+0

你能告訴我怎樣才能改進這個指令? –

+0

我沒有廣泛的角度知識,所以我不能幫你在那裏 – madalinivascu

相關問題