Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have an Object like this

var obj = [
            {
              'id':1,
              'color':'#ff0000',
              'name':'final'
            },
            {
              'id':2,
              'color':'#ffff99',
              'name':'start'
            }
          ];

By using this I am rendering radio button group:

<div class="btn-group" ng-repeat="item in obj">
 <button type="radio" class="btn-group btn-xs btn-group-xs">{{item.name}}</button>
</div>

Here My Question are:

1.How can I apply background-color property on ng-click to button what is present in obj.

2. change the color of button text to contrast/opposite color. (That means if button background color is Black want to change text color to white) .

Here I have tried with ng-class And ng-style but Some where I did wrong.I don't know where it is.

Can any one help me. Thanks

share|improve this question
    
I just answered a question very much like yours. Take a look: stackoverflow.com/questions/24403038/… –  Jonathan Wilson Jun 25 at 8:09
    
@Jonathan Willson. Great Answer but In your class you are using only one color. but in my case I don't know the color. the value of color comes from server. I have already tried with single color –  chandu Jun 25 at 8:13
    
Ok, gotcha. Working on an answer –  Jonathan Wilson Jun 25 at 8:17
add comment

4 Answers

Take this function that inverts hex colors

(source: Automatically change text color to assure readability)

and attach it to your $scope so that it's available in the view:

$scope.invertColor = function (hexTripletColor) {
    var color = hexTripletColor;
    color = color.substring(1);           // remove #
    color = parseInt(color, 16);          // convert to integer
    color = 0xFFFFFF ^ color;             // invert three bytes
    color = color.toString(16);           // convert to hex
    color = ("000000" + color).slice(-6); // pad with leading zeros
    color = "#" + color;                  // prepend #
    return color;
}

Then you use ng-style to set the background and color of each item:

ng-style="{background:item.color, 'color':invertColor(item.color)}"

See the working example here: http://jsfiddle.net/wilsonjonash/eAFVk/2/

share|improve this answer
    
Great answer but I want to apply both css styles when I click on button. not by default –  chandu Jun 25 at 15:06
add comment

I'm use a bit of Jonathan solution to make everything works please see here: jsfiddle

<div ng-app="app">
    <div ng-controller="myCtrl">
        <div class="btn-group" ng-repeat="item in obj">
            <button type="radio" class="btn-group btn-xs btn-group-xs" ng-style="getMyStyle(item)" ng-click="UpdateColor(item)">{{item.name}} {{item.color}}</button>
        </div>
    </div>
</div>

and JS:

var app = angular.module('app', []);

app.controller('myCtrl', function ($scope) {


    $scope.invertColor = function (hexTripletColor) {
        var color = hexTripletColor;
        color = color.substring(1); // remove #
        color = parseInt(color, 16); // convert to integer
        color = 0xFFFFFF ^ color; // invert three bytes
        color = color.toString(16); // convert to hex
        color = ("000000" + color).slice(-6); // pad with leading zeros
        color = "#" + color; // prepend #
        return color;
    }

    $scope.obj = [{
        'id': 1,
            'color': '#ff0000',
            'name': 'final'
    }, {
        'id': 2,
            'color': '#ffff99',
            'name': 'start'
    }];

    $scope.UpdateColor = function (item) {

        item.color = $scope.invertColor(item.color);

    };

    $scope.getMyStyle = function (item) {
        var myStyle = {
            'background-color': item.color,
            color: $scope.invertColor(item.color)
        }
        return myStyle;
    }


});
share|improve this answer
add comment

In terms of displaying opposite colours, from my experience the best readability you can achieve with white/black text over any background colour. I've put some time to study this and that's what I came up with

$scope.RGB = function(colour) {
    if (colour.charAt(0) == "#") {
      colour = colour.substr(1, 6)
    }
    colour = colour.replace(/ /g, "");
    colour = colour.toLowerCase();
    var colour_defs = [{
      re: /^(\w{2})(\w{2})(\w{2})$/,
      process: function(bits) {
        return [parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16)]
      }
    }, {
      re: /^(\w{1})(\w{1})(\w{1})$/,
      process: function(bits) {
        return [parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16)]
      }
    }];
    for (var i = 0; i < colour_defs.length; i++) {
      var re = colour_defs[i].re;
      var processor = colour_defs[i].process;
      var bits = re.exec(colour);
      if (bits) {
        var channels = processor(bits);
        this.r = channels[0];
        this.g = channels[1];
        this.b = channels[2]
      }
    }
    this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
    this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
    this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b)
  }

then

myCol = $scope.RGB('#backgroundColour');
brightness = Math.sqrt(myCol.r * myCol.r * 0.299 + myCol.g * myCol.g * 0.587 + myCol.b * myCol.b * 0.114);
$scope.fontcolour = brightness < 130 ? "#FFFFFF" : "#000000";

any attempts of reversing colours are IMHO bad and often unreadable

here is a demo of inverse which I extended by my blackand white

http://jsfiddle.net/maurycyg/f9Re3/83/

share|improve this answer
    
this works in jQuery. not in angularjs. can youn pls do same thing for angular –  chandu Jun 26 at 5:34
add comment

You could try something like this: add a style property to the elements inside the array:

function MyCtrl($scope) {
  $scope.obj = [
      {
          'id':1,
          'color':'#ff0000',
          'name':'final',
          'style' : {
              'background-color' : ''
          }
      },
      {
          'id':2,
          'color':'#ffff99',
          'name':'start',
          'style' : {
              'background-color' : ''
          }
      }
  ];
}

then, in your view, you can do:

<div ng-app="">
    <div ng-controller="MyCtrl">
        <div class="btn-group" ng-repeat="item in obj">
            <button data-ng-click="item.style = {'background' : item.color}" data-ng-style="item.style" type="radio" class="btn-group btn-xs btn-group-xs">{{item.name}
            </button>
        </div>
    </div>
</div> 

This is a JSFiddle I created. I hope it helps.

EDIT: in Javascript you can add properties to an abject at runtime with a simple loop like this:

for(var i=0; i<$scope.obj.length; i++){
    $scope.obj[i].style = {
        'background-color' : ''
    }
}

You don't have to modify the way you retrieve data from the server (or the format of the data retrieved). Doing this loop you modify only the javascript object you work with. It is a common practice.

share|improve this answer
    
I am getting obj from server. that one can't modify –  chandu Jun 25 at 10:18
    
You can modify the variable you work with, not the data retrieved from the server. Check my EDIT. –  superpuccio Jun 25 at 11:19
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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