2014-05-09 39 views
1

我有一個自定義指令,它內部有一個彈出式菜單,當我點擊我的指令中的一個按鈕時應該顯示它,並且當我點擊時它應該被關閉指令之外。聽一個頁面上多次使用的點擊外部指令

我在列表中使用指令來處理多個項目,因此在頁面上總是會有多個此指令。

現在我有一些正在監聽點擊文檔的代碼。我將這段代碼移到了我的控制器中,因爲它根據頁面上的指令數量進行了x次評估。

有什麼聰明的我可以做的,以保持指令內的所有代碼?

// BOTTOM OF MY CONTROLLER // 

// function to be called when clicking outside the directive/menu 
onDocumentClick = function(event){ 
// if not clicked on an .popup-btn then remove all classnames from popup-menu 
activeNodes = document.getElementsByClassName("popup-menu active"); 
if(activeNodes.length >= 1){ 
    clicked_el = angular.element(event.target); 
    if(!/^popup-btn|popup-menu/.test(clicked_el[0].className)){ 
     for (var i = 0; i < activeNodes.length; i++){ 
      activeNodes[i].className = "popup-menu"; 
      console.log(activeNodes[i]); 
     } 
    } 
} 
}; 

$document.on('click', onDocumentClick); 
}]); 

// END OF CONTROLLER // 

//Directive 
mealplan.directive('recipe', ['$document', function($document) { 
return { 
    restrict: 'AE', 
    scope: { 
     item: '=recipe' 
    }, 
    link: function(scope, elem, attrs) { 
     // toggle the recipe menu 
     scope.toggleMenu = function() { 
      console.log("toggle menu"); 
      // loop throug all menus and reset their class names 
      activeNodes = document.getElementsByClassName("popup-menu active"); 
      if(activeNodes.length >= 1){ 
       for (var i = 0; i < activeNodes.length; i++){ 
        activeNodes[i].className = "popup-menu"; 
        console.log(activeNodes[i]); 
       } 
      } 
      // set the current 
      current = elem[0].getElementsByClassName("popup-menu")[0]; 
      current.className = "popup-menu active"; 
      console.log(current); 
     }; 

     // initializes the states 
     scope.init = function() { 
      //scope.currentMenu = null; 
     }; 

     scope.init(); 

    }, 
    templateUrl: 's/recipes/js/popupMenu-directive.html' 
}; 
}]); 

回答

0

不是很優雅,但你可以使用.off刪除綁定,如果已經存在,然後設置.on事件。

$document.off('click.some-namespace'); 
$document.on('click.some-namespace', function() { ... }); 

對您的事件使用命名空間以保持任何其他點擊事件不變。這樣,無論使用指令的次數如何,事件都應該綁定一次。

+0

事實上,它不是很優雅,但如果它的工作。當我今晚回到家時,我會試一試,如果它符合我的需求,你會得到答案。 –

+0

AngularJS中的jqLit​​e實現不支持名稱空間:on() - 不支持名稱空間,選擇器或eventData - 但是你的方法工作正常。 –

1

在返回選項對象之前在指令中執行的代碼將只執行一次。

Angular-UI documentation

myApp.directive('uiJq', function InjectingFunction(){ 

    // === InjectingFunction === // 
    // Logic is executed 0 or 1 times per app (depending on if directive is used). 
    // Useful for bootstrap and global configuration 
    // Do the binding here 
    return { 
     compile: function CompilingFunction($templateElement, $templateAttributes) { 

      // Logic is executed once (1) for every instance of ui-jq 

      return function LinkingFunction($scope, $linkElement, $linkAttributes) { 
       // Logic is executed once (1) for every RENDERED instance. 
      }; 
     } 
    }; 
}) 

您可以將指令的聲明之後,事件處理程序綁定,這將只執行一次。

+0

這也讓我更好地理解指令是如何構建的。 –