0

I am trying to create accordion to loop my data.it is partially working, but I need to dynamically add new part into accordion. at beginning I need to open the first one, but after user save it and click add,I need to open the second one, and close others. My code is:

<accordion close-others="oneAtATime">
        <accordion-group 
             heading="{{destination.length}}" 
             is-open="status.isFirstOpen" 
             is-disabled="status.isFirstDisabled" 
             ng-repeat="destination in mileage.destionations">
                <select ng-model='destination.Type' 
                    id='type' 
                    ng-options='Type for Type in mileageTypes' 
                    ng-init='mileageTypes[0]' 
                    ng-change='updateReimbur(destination)'>
                </select>
                <select ng-model='destination.Reimbursable' 
                    id='reimbursable' 
                    disabled="true" 
                    ng-options='reimbursable for reimbursable in mileageReimbursment' 
                    ng-init='mileageReimbursment[0]'>
                </select>
        </accordion-group>
  </accordion>

JS:

$scope.mileage.destionations = [{
    Type: '',
    Reimbursable: "Yes",
    Distance: true,
    Odometer: false,
    Total: 0,
    From: '',
    To: ''
}];
$scope.addNewDestionation = function () {
    $scope.NewDestionation = {
        type: '',
        reimbursable: "Yes",
        Distance: true,
        Odometer: false,
        total: 0,
        From: '',
        To: ''
    }
    $scope.mileage.destionations.push($scope.NewDestionation);
}
$scope.status = {
    isFirstOpen: true,
    isFirstDisabled: false
};

How can I always leave the last one(New one) open and close the others?

3
  • Not clear what the question is about. What prevents from applying required logic to $scope.status inside $scope.addNewDestionation? Commented Aug 4, 2015 at 22:13
  • 1
    You wrote close-others="oneAtATime" as in official ui-bootstrap example, but I don't see the declaration of the variable oneAtATime in your javascript. Try simply close-others="true" Commented Aug 4, 2015 at 22:25
  • What's the expected effect of ng-init in the select tags? Commented Aug 4, 2015 at 22:27

3 Answers 3

1

I'm sure you will get that working, by following these hints :

  1. Replace close-others="oneAtATime" with close-others="true".

  2. On all the repeated elements, you are writing : is-open="status.isFirstOpen", which is equivalent to is-open="true". This is your main mistake, as you're saying all groups should be opened. Try to maintain a reference to the opened group. You could maintain an array of statuses but something like that will also do the trick, and avoid you to maintain all statuses :

         is-open="status[$index].isOpen" 
         is-disabled="status[$index].isDisabled" 
    

$index is an angular variable that references the index of the repeated element in the array. I leave you the js logic for the maintenance of the status object.

  1. For the sake of style, correct the typo in destionations (destinations), initialize your default new destination in a variable outside the function addNewDestionation, and push that variable. Like that :

    var newDestination = {
        type: '',
        reimbursable: 'Yes',
        Distance: true,
        Odometer: false,
        total: 0,
        From: '',
        To: ''
    };
    
    $scope.addNewDestionation = function () {
        $scope.mileage.destionations.push(newDestination);
    }
    
Sign up to request clarification or add additional context in comments.

3 Comments

Hi Michael, Thanks for your answer, now I understand my mistake, but the problem, is I need to dynamically add new section into this accordion group, what I want is always keep the last one open and leave others closed, for example, if I click add,there will be new section added(will be opened and close others). how can I let the accrodion know I need to always open the last $index.?
Sure. When you push a new section in the array, réinitialize the status object and activate the flag isOpened for the element at the last position. Something like : status = {}; status[destArray.length - 1] = {isOpened: true}, where destArray is your destination array.
Like that, for all but the last section, status[$index].isOpened will be undefined, and won't be opened as undefined is falsy.
0

close-others attribute takes a boolean value. You should either define

$scope.oneAtATime = true

or

<accordion close-others = "true">

Comments

0

If I've undestood it correctly you could do it like this.

Add a property openState to your destination object and change it like you need it. So keeping the second active could be done be setting every state to false except the second one. It's similar to 2. form Michael's answer and I also think creating a status variable to keep track of the open states is probably better here.

Please have a look at the demo below (it's a reduced version of your code to keep things easier to read) or here at jsfiddle.

angular.module('demoApp', ['ui.bootstrap'])
    .controller('mainController', MainController);

function MainController($scope) {
    var itemCount = 0; // just to have an increasing title
    $scope.oneAtATime = true;
    $scope.mileage = {};
    $scope.mileage.destionations = [{
        Type: '',
        Reimbursable: "Yes",
        Distance: true,
        Odometer: false,
        total: itemCount,
        From: '',
        To: '',
        openState: true
    }];
    $scope.addNewDestination = function () {
        var index = $scope.mileage.destionations.length,
            openState = (index == 1);
        
        angular.forEach($scope.mileage.destionations, function(destination, index) {
            // turn all off except second
            destination.openState = (index == 1);
        });
        
        itemCount++;
        
        var newDestination = {
            type: '',
            reimbursable: "Yes",
            Distance: true,
            Odometer: false,
            total: itemCount,
            From: '',
            To: '',
            openState: openState
        };
        
        
        $scope.mileage.destionations.push(newDestination);
    }
    $scope.status = {
        isFirstOpen: true,
        isFirstDisabled: false
    };
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.2/ui-bootstrap.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.2/ui-bootstrap-tpls.js"></script>
<div ng-app="demoApp" ng-controller="mainController">
    <accordion close-others="oneAtATime">
    <accordion-group is-open="destination.openState" heading="{{destination.total}}" ng-repeat="destination in mileage.destionations">
      {{destination|json}}
    </accordion-group>
  </accordion>
    <button ng-click="addNewDestination()">add</button>
</div>

Comments

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.