change button style according to state angularjs

11,205

Solution 1

Use ng-class directive that should switch class according to any condition

In your case for two cases it should be something like:

<div ng-class="{'true':'button-default','false':'button-unique'}[btn0.state == 'One']" 
     ng-model="btn0" 
     ng-click="evalAnswer(answer, btn0)">{{answer}}</div>

If you want to use multiple cases:

<div ng-class="{'button-default':btn0.state == 'One','button-some':btn0.state == 'Two','button-else':btn0.state == 'Three'}" 
         ng-model="btn0" 
         ng-click="evalAnswer(answer, btn0)">{{answer}}
</div>

Demo Fiddle

Solution 2

There are multiple ways to accomplish what you are wanting:

  • ng-class use to set classes based on conditions

  • ng-style used when you can not define a class or just need to change simple css

I suggest using ng-class if the styling is complicated or multiple changes are needed in the css. the ng-class accepts an expression that can be evaluated to an array of class names, a string of delimited class names or a map of object names.

I think something like this should work for two classes:

<div ng-class="{{'someBoolean' && 'class-when-good' || 'class-when-nope'}}">{{answer}}</div>

or a ternary (using angular version above 1.1.5)

<div ng-class="'someBoolean' ? 'class-when-good' : 'class-when-nope'">{{answer}}</div>

Note if you need to apply a default class in addition to a conditional class this is how to would be done:

<div ng-class="{{'someBoolean' && 'class-default class-when-good' || 'class-default class-when-nope'}}">{{answer}}</div>

or a ternary with default

<div ng-class="'someBoolean' ? 'class-default class-when-good' : 'class-default class-when-nope'">{{answer}}</div>

The other option and the one I think might work best for your problem is the ng-style. Since you are only needing to change the button color in might be better to simply change that color rather then apply different classes.

<div ng-style="answer === 'good' && {'background-color' : 'green'} || 
                 answer === 'nope' && {'background-color' : 'red'}">{{answer}}</div>

assuming: that the {{answer}} is set to the values evaluated (answer is good or nope).

Edit: For the style conditional it needs to be set in your controller, if answer can not be used in the conditional test. It looks like you have an object btn0, and each of those objects could have a property (btn0.isGood) the could be set in the evalAnswer(answer, btn0) click event and would result in the changing the style.

Share:
11,205
SKYnine
Author by

SKYnine

Creative technologist for a production / postproduction company in the film industry

Updated on June 04, 2022

Comments

  • SKYnine
    SKYnine almost 2 years

    I have a problem finding the way to style a button according to it's state. I have a question, and four answer tiles.

    each tiles is coded like this:

    <div class="button-default" ng-model="btn0" ng-click"evalAnswer(answer, btn0)">{{answer}}</div>
    <div class="button-default" ng-model="btn1" ng-click"evalAnswer(answer, btn1)">{{answer}}</div>
    <div class="button-default" ng-model="btn2" ng-click"evalAnswer(answer, btn2)">{{answer}}</div>
    <div class="button-default" ng-model="btn3" ng-click"evalAnswer(answer, btn3)">{{answer}}</div>
    

    On the controller side I have a function that, on click, look at the answer and return "good" if the answer is correct, and "nope" if the answer is not good.

    What I would like is to add button styling within these good and nope states so the button become red in case the answer is nope, and green if it's the good answer. I already created the class and I only need to change "button-default" to "button-good" or "button-wrong". Also, It needs to change only the clicked button.

    Any idea on the way to do that?

  • SKYnine
    SKYnine almost 10 years
    that's my question. How to make it react based on answer's state: good or nope? Also, from what I know, ng-style doesn't handle multiple states ?
  • SKYnine
    SKYnine almost 10 years
    using ng-class, could I add several states? like this: ng-class="{'button-default': <condition>, 'button-good': <condition> }" ? Also, does condition react to the scope? the evalAnswer() is in the scope and so it my if/else statement returning good/nope. I'll get deeper look into ng-class
  • Maxim Shoustin
    Maxim Shoustin almost 10 years
    @SKYnine added demo in Fiddle
  • SKYnine
    SKYnine almost 10 years
    Thanks, that sounds good. I think I can handle this and integrate it. will return with validation if that works! thanks for your help
  • Jared Reeves
    Jared Reeves almost 10 years
    I edited the original answer, I hope this helps. In the above I was assuming that the default class should be applied regardless of condition, let me know if this is not the case.
  • SKYnine
    SKYnine almost 10 years
    that sounds to be an awesome solution. Does the boolean could come from the scope. Let set $scope.isGood = false; in my if/else I change isGood according to states and then I use isGood in ng-class? Will try this out thanks ! And yes, you're right, there is a default class which is used before the answer is checked.
  • Jared Reeves
    Jared Reeves almost 10 years
    yes it could, if you use a $scope.isGood then the someBoolean would be ng-class="'isGood' && 'class-default class-when-good' || 'class-default class-when-nope'}}"
  • Jared Reeves
    Jared Reeves almost 10 years
    Do you need to have both the default class and the good class applied when the condition is good?
  • SKYnine
    SKYnine almost 10 years
    no, only one at a time. I have four possible answer, only one is correct. I just want to "express" if the answer is good or not when clicking on one of the 4 buttons by changing its style. The 3 other button remain in default style while the clicked one becomes green if the selected answer is good, and red if not. When the good answer is selected, the question/answers changes.
  • Jared Reeves
    Jared Reeves almost 10 years
    ok, I definitely think the the ng-style is your best option then.
  • SKYnine
    SKYnine almost 10 years
    So I made a reduced test and here are my results: html '<div ng-model="btn0" ng-class="{{'isGood' && 'default good' || 'default wrong'}}" ng-click="evalAnswer(opt2)">{{opt1}}</div>' controller '$scope.opt1 = "hello"; $scope.answer = "hi"; $scope.isGood = false; $scope.evalAnswer = function(answ) { if(answ == $scope.answer){ console.log("right"); $scope.isGood = true; } else{ console.log("wrong"); $scope.isGood = false; } }' conditl with default return angular error ternary return the good (green background) class directly.
  • SKYnine
    SKYnine almost 10 years
    About the ng-style: where does the good and nope came from? my controller? how do I check the state of the answer ? I have trouble understanding the logic here
  • Jared Reeves
    Jared Reeves almost 10 years
    the conditional test would come from your controller, most likely you will have a property on each button that has is set to a Boolean for good/nope. I will make some changes to answer.
  • Jared Reeves
    Jared Reeves almost 10 years
    If you want some more detailed help post a plunker or fiddle and I can help you further.
  • SKYnine
    SKYnine almost 10 years
    Worked like a charm. The only negative point is that I need to define each button state within the scope. I wil try to make this generic. Anyway thanks!
  • SKYnine
    SKYnine almost 10 years
    Maxim's answer worked perfectly within my actual function. However, Im very interested in learning about your method. I can't make a fiddle right now but I'll update you asap if you don't mind teaching me.