1

I am new to angular and trying to change a style when clicking. I have a template and I create 2-3 content space using the same template on the page. When user clicks on a "more" link I want to expand that section. I am able to do that using the following code which then triggers a css

<a href="#" ng-click="isActive = !isActive"><strong>more</strong></a>

The place I am struggling is, if the user clicks another section to expand I want to collapse the previously expanded section and expand the current section, whereas currently the expansion applies to the current section.

2 Answers 2

4

You'll want more than just a boolean true/false variable if you want to collapse the others. Here's one approach.

<a ng-click="active = 0" ng-class="{show: active==0}"></a>
<a ng-click="active = 1" ng-class="{show: active==1}"></a>

This can also be combined with ng-repeat if you so desire

<a ng-repeat="section in sections" ng-click="active = $index" ng-class="{show: active==$index}"></a>
Sign up to request clarification or add additional context in comments.

1 Comment

ngClass allows for multiple css definitions seperated by comma: ng-class="{'show': active, 'hide': !active}"
0

If you only want to have one item selected at any given time, drive this through selectedItem on the $scope and use ng-if in the template to check if the selected item is the current item. Example:

angular.module('myApp', [])

.controller('MainController', function ($scope) {
    var items = [],
        vm = {};

    // properties
    $scope.vm = vm; 
    vm.items = items;
    vm.selectedItem = null;
    
    //methods
    vm.setItem = function (item) {
        // reset current item to more
        if (vm.selectedItem) {
          vm.selectedItem.detailsText = 'More';
        }

        // collapse if selecting same item
        if (item === vm.selectedItem) {
            vm.selectedItem = null;
            return;
        }
        
        item.detailsText = 'Less';
        vm.selectedItem = item;
    };
    
    activate();
    
    // initialization logic
    function activate() {   
        for(var i = 0; i < 15; ++i) {
            items.push({id: i, title: 'Item: ' + i, details: 'Item ' + i + ' Details', detailsText: 'More'});
        }
    }
});
html {
    box-sizing: border-box;
}

*, *:before, *:after {
    box-sizing: inherit;
}

a {
  color: #004b8d;
  text-decoration: underline;
  cursor: pointer;
}

a:hover {
  color: #2c88e6;
  text-decoration: none;
}

.container {
    width: 500px;
    border: 1px solid black;
}

.item {
    padding: 12px;
    border-bottom: 1px solid gray;
}

.item:last-child {
    border: 0;
}

.details {
    margin-left: 10px;
    color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MainController" class="container">
    <div class="item" ng-repeat="item in vm.items">
        {{item.title}} <a ng-click="vm.setItem(item)">{{item.detailsText}}</a>
        <div class="details" ng-if="vm.selectedItem === item">
            {{item.details}}
        </div>
    </div>
</div>

This will make it easier to update through the controller and template, rather than having to duplicate parts of the template to deactivate for instance. Any logic also lives directly inside the controller which is better for unit tests. For example:

it('should update selected item', function () {
    // ... initialize controller and $scope properties
    var item = {};
    $scope.vm.setItem(item);
    expect($scope.vm.selectedItem).toBe(item);
    expect(item.detailsText).toBe('Less');
});

2 Comments

Pat, Is it possible to do this in a directive rather in controller
Yes -- what parts would you want in a directive? The entire item and the expand collapse part? You should be able to take this idea and extend it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.