HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Handling shared state among a lot of elements in Angular

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
handlingamongsharedelementsangularlotstate

Problem

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==''

Solution

Your View looks fine (HTML and CSS). However, representing the state of your data elements with two string variables that may or may not be storing the "name" field on the parent data object is a very bad way of representing state.

The guiding principal for these design questions: your object model should make it impossible to ever represent an inconsistent or meaningless state. With your object model there are many ways to represent inconsistent and meaningless states, for example:

  • It's possible for a data item to be simultaneously in state Med


and state Max

  • If medElement and maxElement variables contain


values which are not equal to the name field on the parent object,
those values are ignored

As a result your controller code is needlessly complex and very difficult to read.

Solution:

Represent the state of your data objects with an enum called ElementSize that can take exactly one of three possible state values: minimum, medium, and maximum. Then, use the ng-switch directive to specify what html you want to render for each of the three possible states.

Context

StackExchange Code Review Q#63606, answer score: 4

Revisions (0)

No revisions yet.