The best (most efficient) way to display a menu of dynamic options in angularjs

Let's say we have many elements in the user interface. When the user clicks on an element, the user interface should represent the popup / dialiog / overlay element with some parameters, actions, etc.

I currently see two options:

  • Duplicate the overlay element for each element and hide it until the corresponding element is clicked. Like in this fiddle: http://jsfiddle.net/urPww/1/

    <div ng-show="currentItem"> showing options for: {{currentItem.name}} </div> <li ng-repeat="item in items" ng-click="showOptions(item)"> {{item.name}} </li>

  • Place the overlay user interface once and keep track of which item was last clicked. Demo: http://jsfiddle.net/aVnPT/5/

    <li ng-repeat="item in items" ng-click="showOptions(item)"> {{item.name}} <span ng-show="item.showingOptions"> <br/>showing options for: {{item.name}} </span> </li>

The first solution is inefficient. However, I cannot figure out how to show the overlay user interface, rather than clicking on an element in the second. Any ideas?

+6
source share
2 answers

You can use one element by passing in $event as a parameter to your ng-click function. Then you can get the position of the mouse click relative to the document

 app.directive('container', function () { var offset = { left: 40, top: -20 } return function (scope, element, attributes) { var $oLay = angular.element(document.getElementById('overlay')) scope.showOptions = function (item,$event) { var overlayDisplay; if (scope.currentItem === item) { scope.currentItem = null; overlayDisplay='none' }else{ scope.currentItem = item; overlayDisplay='block' } var overLayCSS = { left: $event.clientX + offset.left + 'px', top: $event.clientY + offset.top + 'px', display: overlayDisplay } $oLay.css(overLayCSS) } } }); 

Not sure if angular normalizes clientX and clientY jQuery way for different browsers. Not all browsers use the same convention for event position properties. We removed the ng-show element from the overlay element so that the style attributes could be controlled from the directive and not using the angular compiler due to the time and giving it an identifier.

DEMO: http://jsfiddle.net/jJyTf/

+2
source

Option 2 can work with a directive that dynamically places the overlay option next to the click of an element using dom manipulation (see @charlietfl answer). You get simpler HTML but much more complex js / angular code.

However, I think option 1 is the right idea, and you can just clean it up a bit. You can get rid of the directive and have a controller method as simple as:

 $scope.showOptions = function(item) { $scope.currentItem = item; } 

Look here:

http://jsfiddle.net/qxF3A/3/

I would love to add a little (minimal) duplication in my view / template if it greatly simplifies my controllers and avoids the need for a custom directive.

0
source

All Articles