3

I searched about my problem, and I could not find my answer and I'm just looking for the solution with the best performance and less code.

I have some drop-down menus and I want to have just one function to show and hide the menus on click on their buttons, by JavaScript or by JQuery this is simple and does not add more codes (atributes) to the HTML elements and it means lighter DOM.

Imagine these are my buttons, actually my links (HTML):

<a class="first-menu" href="#">First link</a>
<a class="second-menu" href="#">Second link</a>
<a class="third-menu" href="#">Third link</a>


<div class="first-menu-div">This is first MENU</div>
<div class="second-menu-div">This is Second MENU</div>
<div class="third-menu-div">This is Third MENU</div>

And this can be my JQuery:

  $("a").click(function() {
    var class_name = $(this).attr('class');
    $("div").hide();
    $("." + class_name + '-div').show();
  });

Simple JSfiddle demo

In this case, by a simple JavaScript (JQuery) code we can hide all menus and show the menu we need according to the class of the clicked link. We did not added attributes just for showing or hiding the menu by clicking a certain link, and we can simply expend the program by adding menu or link or even changing function.

Now I want to know how we can have something like this function in Angular and with Angular's standards. For example I can do this by these codes:

<a ng-click="showHideMenu('menu1')">Show menu 1 </a>
<a ng-click="showHideMenu('menu2')">Show menu 2 </a>

And here may be the controller:

$scope.OpenHeaderMenu= function(elementClass){
                $(".menus > div").hide();
                $(elementClass).show()
                 //Just imagine Angular also has hide() and show() OR A way to use variable to set ng-show and ng-hide to the elements we want
            };

Is there any way to do this by Angular like JQuery and get the rid of ng-show and ng-hide and use functional programming instead of adding attributes and lots of if | else to controller to hide or show simple menus?

I want to have these menus lots of time in my pages and I prefer to have a simple function to call and having less code and better performance.

I hope my question be clear

mvermand
  • 5,829
  • 7
  • 48
  • 74
Mohammad Kermani
  • 5,188
  • 7
  • 37
  • 61
  • Why are you even using angular if you want to do things this way? For portability simply create a directive and wrap it in it's own module – charlietfl Jun 13 '16 at 21:15
  • @charlietfl I'm new in Angular and I just asked to learn more about it and change the wrong things I know about Angular – Mohammad Kermani Jun 13 '16 at 21:22
  • first thing to do is take jQuery.js right out of the page then. Strongly suggest reading http://stackoverflow.com/q/14994391/1175966 – charlietfl Jun 13 '16 at 21:25
  • @charlietfl I appreciate your good advice.Can you please spend a little time to answer my question and correct my fault logic in programming with Angular!? Thank you – Mohammad Kermani Jun 13 '16 at 21:30
  • @charlietfl I'm reading the link you sent me, that is really nice and I was wrong about Angular. Thanks – Mohammad Kermani Jun 13 '16 at 21:36

3 Answers3

8

your logic is wrong, you should not be able to modify dom objects from a controller, anyway, you can use a combination of ng-show, ng-hide and $scope to update your view.

you should do something like

$scope.click= function(showitem){
    $scope.showItem = showItem;
};

in your view:

<a ng-click="click(true)">Show menu 1 </a>

<div ng-show="showItem">
some item
</div>

instead of modifying elements in your controller try to make a directive but that's another history.

I just googled this fiddler is something similar of what you would like to do.

hope that helps.

Edit: you just need to pass a variable to ng-show with an expression to show the element with the specified condition.

$scope.click = function(item){
    $scope.cClass = item
}

<a class="first-menu" ng-click="click(1)" href="#">First link</a>
<a class="second-menu" ng-click="click(2)" href="#">Second link</a>
<a class="third-menu" ng-click="click(3)" href="#">Third link</a>

<div class="first-menu-div" ng-show="cClass == 1">
    This is first MENU
</div>
<div class="second-menu-div" ng-show="cClass == 2">
    This is Second MENU
</div>
<div class="third-menu-div" ng-show="cClass == 3">
    This is Third MENU
</div>

check my fiddler

pedrommuller
  • 15,741
  • 10
  • 76
  • 126
  • In your code, this just works for showing one menu, and how can I show more than one menu using this, I mean **showItem** in your code is a variable that I just should use with one of my div(s) and I also need to hide all other menus before showing the certain menu. Thanks – Mohammad Kermani Jun 13 '16 at 21:20
  • check my update I got a working fiddler as an example – pedrommuller Jun 13 '16 at 21:44
  • Thanks Jack, that worked for me. I just have a question from Angular logic as you mentioned in start of your answer, the way you wrote the code, is it correct and standard way that Angular is? – Mohammad Kermani Jun 13 '16 at 21:55
  • well that depends on what you need, definitely when I modify DOM I just want to use a directive, but that again will depend on your situation, check this article http://ng-learn.org/2014/01/Dom-Manipulations/ that may help to wrap your logic around angular-js – pedrommuller Jun 13 '16 at 21:58
  • And what about the exact code you write in jsfiddle? Is it correct and standard way that an Angular program should be? Or you just made it for me as an example – Mohammad Kermani Jun 13 '16 at 22:00
  • IMHO that's fine for that sole purpose if you want to extend beyond that (modify other attributes in the DOM do more complex expressions) you might do a directive, but again that depends on what you need, good luck – pedrommuller Jun 13 '16 at 22:04
5

You can use ngshow as the code sample below without any classes or selectors

(function () {
  'use strict';

  angular
    .module('testApp', [])
    .controller('HeaderCtrl', function () {
      this.target =false;
  });


}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="testApp">
    <div ng-controller="HeaderCtrl as hd">
      <a href="#" ng-click="hd.target= 'first'">First link</a>
      <a href="#" ng-click="hd.target= 'second'">Second link</a>
      <a href="#" ng-click="hd.target= 'third'">Third link</a>


      <div ng-show="hd.target == 'first'">
        This is first MENU
      </div>
      <div ng-show="hd.target == 'second'">
        This is Second MENU
      </div>
      <div ng-show="hd.target == 'third'">
        This is Third MENU
      </div>

    </div>
  </div>
Mohamed Elfiky
  • 106
  • 1
  • 7
0

I am not sure if this solves your problem but you could use ng-switch and the ng-switch-when

$scope.click = function(itemNum){
  $scope.displayTab = itemNum;
}

in your view you could have:

<a ng-click="click(1)">Show menu 1 </a>
<a ng-click="click(2)">Show menu 2 </a>

<ANY ng-switch="displayTab">
  <ANY ng-switch-when="1">...</ANY>
  <ANY ng-switch-when="2">...</ANY>
  <ANY ng-switch-default>...</ANY>
</ANY>

You could get more creative with the top part of the view but that is just a hard-coded example

Jake
  • 402
  • 1
  • 4
  • 12