I am working on a project in Angular where I have a number of similar data objects. When you click on anyone of them it's state and amount of data shown will change. All of the objects start in the minimal state, when you click on one it becomes medium. From a medium you can click on the button to go to maximum or click anywhere else on it to go back down. There can only be one medium or maximum at a time. If there is one medium there can be no maximum, and vice versa.
Since all of the objects are by default min, I don't track that. I use a string to track which element is in an expanded state. Then I compare that objects key and the string in an ng-if to change its what is being shown. The size is managed by a conditional class, and CSS.
I chose ng-if, because there maybe a lot of elements loaded in the beginning, but there can only be one med/max at a time. I would rather load the med/max when the user wants it, instead of loading all of the med/max at that start and use ng-show for state view.
Is there a cleaner way to handle state change among many related objects? Does Angular have something to deal with this?
angular.module('SizeAndState', [])
.factory('Data', function() {
return {
query: function() {
return {
a:{ name: 'A', date: '1/2/03', number: 1},
b:{ name: 'B', date: '4/5/06', number: 2},
c:{ name: 'C', date: '8/9/10', number: 3},
d:{ name: 'D', date: '3/2/01', number: 4},
e:{ name: 'E', date: '1/2/14', number: 5},
}
}
};
})
.controller('SizeAndStateController', ['$scope', 'Data', function($scope, Data) {
$scope.toMin = function (clickEvent){
clickEvent.stopPropagation();
$scope.medElement = '';
$scope.maxElement = '';
};
$scope.toMed = function (elementName, clickEvent){
if($scope.maxElement=='') {
if($scope.medElement == elementName){
$scope.toMin(clickEvent);
} else {
$scope.medElement = elementName;
}
}
};
$scope.toMax = function (clickEvent){
clickEvent.stopPropagation();
$scope.maxElement = $scope.medElement;
$scope.medElement = '';
};
$scope.data = Data.query();
$scope.medElement = '';
$scope.maxElement = '';
}]);
.campaign{
display: inline-block;
width: 100px;
height: 100px;
background-color: #ff685b;
border: 1px solid #ffffff;
color: #ffffff;
vertical-align: top;
}
.campaign.med{
width: 125px;
height: 125px;
}
.campaign.max{
width: 150px;
height: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="SizeAndState">
<div ng-controller="SizeAndStateController">
<div class="campaign"
ng-repeat = "element in data"
ng-class="{'med':medElement==element.name, 'max':maxElement==element.name}"
ng-click="toMed(element.name, $event)">
<span>{{element.name}}</span> <span ng-if='medElement!=element.name && maxElement!=element.name'>Min</span>
<span ng-if='medElement==element.name'>
<span>Med</span>
<h5>{{element.date}}</h5>
<button class="btn"
ng-click="toMax($event)">
to Max
</button>
</span>
<span ng-if='maxElement==element.name'>
<span>Max</span>
<h5>{{element.date}}</h5>
<h5 ng-if='maxElement==element.name'>{{element.number}}</h5>
<button
ng-if="maxElement == element.name"
ng-click="toMin($event)">
to Min
</button>
</span>
</div>
</div>
</div>