0
\$\begingroup\$

I'm using AngularJS and I have a watch task in my controller that needs to be dried up if possible.

Basically it watches for state changes in my front end. I have 3 buttons: add, edit, and delete which will toggle these states. I only want one to be active at once.

My buttons:

<button ng-click="actions.add === false ? actions.add = true : actions.add = false">Add</button>
<button ng-click="actions.edit === false ? actions.edit = true : actions.edit = false">Edit</button>
<button ng-click="actions.delete === false ? actions.delete = true : actions.delete = false">Delete</button>

Snippet from my controller:

$scope.actions = {
  add: false,
  edit: false,
  delete: false
}

$scope.$watch('actions', function() {

  if ($scope.actions.add === true) {
    $scope.actions.edit = false;
    $scope.actions.delete = false;
  }
  else if ($scope.actions.edit === true) {
    $scope.actions.add = false;
    $scope.actions.delete = false;
  }
  else if ($scope.actions.delete === true) {
    $scope.actions.add = false;
    $scope.actions.edit = false;
  }
});
\$\endgroup\$
1
\$\begingroup\$

I assume that when you say that you want your code to be "dried" up, you want your code to be more DRY, right?

Well right now, you are doing quite a bit of repeating: you've created individual conditional statements for each property of an object.

Your code would be much more DRY if you iterated through the object and checked the properties as you iterated.

Since we are handling an object, let's use a for/in loop:

for(var i in $scope.actions) {

}

In every conditional statement that you wrote, you checked to see if a property was equal to true.

That should be the first thing we check here:

for(var i in $scope.actions) {
    if($scope.actions[i])

    }
}

Notice how there is no === true at the end of the conditional? JavaScript already checks to see if the conditional reduces to true automatically.

Now we have to find a way to set the other two values in the object to false in a DRY way.

I think it would be best to create a function that takes in one argument that is the name of the property that should not be set to false, and then the function sets the other properties to false

That would look like this:

function setPropertiesToFalse(obj, except) {
    for(var i in obj) {
        if(i != except) {
            obj[i] = false;
        }
    }
}

Now the main code would look like this:

for(var i in $scope.actions) {
    if($scope.actions[i]) {
        setPropertiesToFalse($scope.actions, i);
        break;
    }
}

I added a break statement into your code because the original code uses if/else, so if a conditional were to pass, the rest would not be checked.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.