Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a set of headings (<h3>) that when clicked, they hide/show their corresponding sections.

I have achieved this by using ng-show/ng-hide and then calling a $scope variable isInactive/isActive.

What i would like to know, is if the same result can be achieved, without the need for using JS within $scope.isInactive and $scope.isActive and logic be placed in the HTML markup? Possibly with the us of ng-class?

HTML:

<div ng-app="">
  <div ng-controller="EventController">
    <div class="tabs">
         <h3 class="" id="tab-{{$index}}-0"><a id="1" data="{{$index}}" ng-click="switch($event)">1 - 5 Years</a></h3>

         <h3 class="inactive" id="tab-{{$index}}-1"><a id="2" data="{{$index}}" ng-click="switch($event)">6 - 10 Years</a></h3>

         <h3 class="inactive" id="tab-{{$index}}-2"><a id="3" data="{{$index}}" ng-click="switch($event)">11 - 15 Years</a></h3>

         <h3 class="inactive" id="tab-{{$index}}-3"><a id="4" data="{{$index}}" ng-click="switch($event)">16 - 20 Years</a></h3>

        <div class="clear" data="{{$index}}" ng-hide="isInactive('#tab-'+{{$index}} + '-0')">1 - 5 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
        <br>
        <div class="clear" ng-show="isActive('#tab-'+{{$index}} + '-1')">6 - 10 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
        <br>
        <div class="clear" ng-show="isActive('#tab-'+{{$index}} + '-2')">11 - 15 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
        <br>
        <div class="clear" ng-show="isActive('#tab-'+{{$index}} + '-3')">16 - 20 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
    </div>
  </div>
</div>

JS:

function EventController($scope) {

$scope.
switch = function (e) {
    var target = e.target || e.srcElement;
    var elem = angular.element(target);
    var parent = elem.parent();
    var allHeadings = parent.parent().find("h3");

    angular.forEach(allHeadings, function (aHeading) {
        var child = angular.element(aHeading);
        child.addClass("inactive");
    });
    parent.removeClass("inactive");
}

$scope.isInactive = function (e) {
    var elem = angular.element(document.querySelector(e));
    if (elem.hasClass("inactive")) {
        return true;
    } else {
        return false;
    }
};

$scope.isActive = function (e) {
    var elem = angular.element(document.querySelector(e));
    if (elem.hasClass("inactive")) {
        return false;
    } else {
        return true;
    }
};

}

My jsFiddle: http://jsfiddle.net/oampz/Wr79J/2/

share|improve this question

3 Answers 3

up vote 1 down vote accepted

Yes, you have correctly identified this the apt place for using ng-class.

It is possible to do only using HTML and a minimalistic controller: http://jsfiddle.net/Wr79J/4/

JS

function EventController($scope) {
    $scope._activeTab = 1;
}

HTML

<div ng-app="">
    <div ng-controller="EventController">
        <div class="tabs">
             <h3 ng-class="{ 'inactive': _activeTab !== 1, 'active': _activeTab == 1 }">
               <a id="1" ng-click="_activeTab=1">1 - 5 Years</a></h3>

     <!-- .... -->

    <div class="clear" ng-show="_activeTab == 1">
       1 - 5 Years Text - Lorem ipsum ...
    </div>

</div>

Note: I think you were using {{$index}} from a scope this part of the template had inherited. I have left that untouched in the example.

Though this works, this code is not very maintainable. You may want to use more descriptive names for the tabs instead of 1, 2, 3, and 4.

You can get rid of the controller completely using an ng-init="_activeTabe = 1" on the container div, but it is not the correct use of ng-init.


Also, it is not considered good practise to manipulate the DOM in any way from the controller (I am looking at the addClass/removeClass in the code). If it is necessary, then one should use directives (e.g. ng-class) for the manipulation.

share|improve this answer
    
thanks for the detailed solution, what do you think to guru's solution with no JS at all? –  Oam Psy Jun 3 at 10:55
1  
@OamPsy He is using the ng-init trick which is not condoned in the docs. I have mentioned it in my answer after the Note. –  musically_ut Jun 3 at 11:00
    
Thanks for outlining this –  Oam Psy Jun 3 at 11:04
1  
@OamPsy ng-class="{ 'tabs-inactive' : _activeTab !== 1, ...}". There are several ways of using ng-class and I am using the one in which the keys of the Object passed are the class names which are applied to the element if the value is truthy. You can add quote marks around the class names. I didn't add the quotation marks around the class names active and inactive out of laziness. Updated the answer. –  musically_ut Jun 3 at 11:26
1  
@OamPsy I have used single quotes to prevent interference with the double quotes used for the attribute value. –  musically_ut Jun 3 at 12:39

You can just set a variable to set the active tab.

<div class="tabs">
  <h3 ng-click="range=1">1-5</h3>
  <h3 ng-click="range=2">6-10</h3>
  <div class="clear" ng-show="range==1">1 - 5 Years Text</div>
  <div class="clear" ng-show="range==2">6 - 10 Years Text</div>
</div>
share|improve this answer

Here is an example - http://plnkr.co/edit/NTVPbOC5k7HKo88qp6vN?p=preview with no javascript code for the above logic.

  <div>
    <div>
      <div class="tabs">
        <h3 ng-init="active=1" ng-click="active=1" ng-class="{true:'active', false:'inactive'}[active==1]"><a >1 - 5 Years</a></h3>
        <h3 ng-click="active=2" ng-class="{true:'active', false:'inactive'}[active==2]"><a >6 - 10 Years</a></h3>
        <h3 ng-click="active=3" ng-class="{true:'active', false:'inactive'}[active==3]"><a >11 - 15 Years</a></h3>
        <h3 ng-click="active=4" ng-class="{true:'active', false:'inactive'}[active==4]"><a >16 - 20 Years</a></h3>

        <div ng-show="active==1">1 - 5 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
        <br>
        <div ng-show="active==2">6 - 10 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
        <br>
        <div ng-show="active==3">11 - 15 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
        <br>
        <div ng-show="active==4">16 - 20 Years Text - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris</div>
      </div>
    </div>
  </div>
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.