Reputation: 2588
Seems like a simple problem but I'm actually having trouble with it.
Basically I have a ng-repeat of buttons and then a block of text after that clicking the button will show. However, when I click a button I want to hide the blocks of text from all the other buttons and remove the active states from the other buttons. Basically only 1 button block of text should be shown at a time.
Seems easy, but the way ng-hide handles scope (scope: true) means I can't really look into the other scopes and turn each of them off. The other thing is that I don't want to alter the actual array from ng-repeat if at all possible. This is data from an API that I have to send back and I'm attempting to not alter the actual data structure if I can.
<div class="row" ng-repeat="button in buttons">
<div class="col-sm-2">
<button ng-click="showInfo = !showInfo" class="btn btn-primary">{{button.name}}</button>
</div>
<div ng-show="showInfo" class="col-sm-3">
<div class="alert alert-success">{{button.extraInfo}}</div>
</div>
</div>
And JS
app.controller('MainCtrl', function($scope) {
$scope.buttons = [
{ name: 'One', extraInfo: 'Extra info for button 1' },
{ name: 'Two', extraInfo: 'Extra info for button 2' },
{ name: 'Three', extraInfo: 'Extra info for button 3' }
];
});
Upvotes: 1
Views: 9075
Reputation: 952
If you don't want to change the actual array, then maintain another object or array which will hold the key to each button's show/hide state.
$scope.showInfo = {};
$scope.buttons = [
{ name: 'One', extraInfo: 'Extra info for button 1' },
{ name: 'Two', extraInfo: 'Extra info for button 2' },
{ name: 'Three', extraInfo: 'Extra info for button 3' }
];
$scope.changeShowInfo = function(index) {
for(var prop in $scope.showInfo) {
$scope.showInfo[prop] = false;
}
$scope.showInfo[index] = true;
};
Upvotes: 3
Reputation: 1018
You want 1 button active each time, so you better use radio buttons with a currentItem kept in the scope by using ng-bind.
HTML:
<body ng-controller="MainCtrl">
<div name="myForm">
<div ng-repeat="button in buttons">
<label>
<input type="radio" ng-model="$parent.selectedItem" ng-value="button"> {{button.name}}
</label>
</div>
</div>
<div class="alert alert-success">Extra info: {{selectedItem.extraInfo}}</div>
</body>
Didn't need to change your JS.
Upvotes: 0
Reputation: 49195
I suggest to create new array which has the same length as buttons
array, and this array will hold boolean values to indicate where the item active or not.
I didn't log in to plunk so here the modified version of yours.
index.html
<body ng-controller="MainCtrl as vm">
<div class="row" ng-repeat="button in buttons track by $index">
<div class="col-sm-2">
<button ng-click="vm.setActive($index)" ng-class="vm.isActive[$index] ? 'btn btn-primary' : 'btn'">{{button.name}}</button>
</div>
<div ng-show="vm.isActive[$index]" class="col-sm-3">
<div class="alert alert-success">{{button.extraInfo}}</div>
</div>
</div>
</body>
app.js
app.controller('MainCtrl', function($scope) {
$scope.buttons = [
{ name: 'One', extraInfo: 'Extra info for button 1' },
{ name: 'Two', extraInfo: 'Extra info for button 2' },
{ name: 'Three', extraInfo: 'Extra info for button 3' }
];
var vm = this;
vm.isActive =[];
for(var i=0, len=$scope.buttons.length; i < len; i++){
vm.isActive[i] = false;
}
vm.setActive = function(ind) {
for(var i=0, len=vm.isActive.length; i < len; i++){
vm.isActive[i] = i===ind;
}
}
});
Upvotes: 4