How to change class separately for each element? (Angular) - css

I have a demo when on click it changes the class back and worth, but I can't figure it out how to change them separately.
Here's a demo for better explanation: http://jsfiddle.net/pWG2S/1260/
I could add similar line of code to the js with class2, class3 etc, but the problem is that this class will be repeated a lot of times. If you have any ideas on how to fix this problem that would be great. Thank you in advance
$scope.changeClass = function(){
if ($scope.class === "rotated")
$scope.class = "rotated2";
else
$scope.class = "rotated";
};

Just change class to be an array and then pass each index:
$scope.changeClass = function(i){
if ($scope.class[i] === "red")
$scope.class[i] = "blue";
else
$scope.class[i] = "red";
};
Fiddle here

HTML:
<body ng-app="ap" ng-controller="con">
<div ng-class="class">{{class}}</div>
<button id="button1" ng-click="changeClass($event)">Change Class</button>
<div ng-class="class1">{{class1}}</div>
<button id="button2" ng-click="changeClass($event)">Change Class</button>
</body>
JS:
var app = angular.module("ap",[]);
app.controller("con",function($scope){
$scope.class = "red";
$scope.class1 = "red";
$scope.changeClass = function(event){
console.log(event.currentTarget.id);
if(event.currentTarget.id === "button1")
if ($scope.class === "red")
$scope.class = "blue";
else
$scope.class = "red";
else if(event.currentTarget.id === "button2")
if ($scope.class1 === "red")
$scope.class1 = "blue";
else
$scope.class1 = "red";
};
});
Fiddle
I should have refactored the code a bit more. However my initial idea is that you will need to pass in $event along with your ng-click and provide id's to button in order to uniquely identify them through event.currentTarget.id
Also the fiddle of Nghi Nguyen makes more sense to do it with directive since your same set of elements for twice. Encapsulate them inside a directive. This way you don't even have to use $event to determine your button's id and the controller will only handle changeClass for a particular directive.
EDIT1:
var app = angular.module("ap",[]);
app.controller("con",function($scope){
$scope.class = "red"; // default class
$scope.changeClass = function($event){
if ($($event.target).prev().hasClass('red')) {
$($event.target).prev().removeClass('red').addClass('blue');
} else {
$($event.target).prev().removeClass('blue').addClass('red');
}
};
});
HTML:
<body ng-app="ap" ng-controller="con">
<div ng-class="class">{{class}}</div>
<button ng-click="changeClass($event)">Change Class</button>
<div ng-class="class">{{class}}</div>
<button ng-click="changeClass($event)" >Change Class</button>
</body>

How about this?
Controller
var app = angular.module("ap",[]);
app.controller("con",function($scope){
$scope.klasses = ["red", "blue", "yellow"];
$scope.klassIndex = 0;
$scope.changeClass = function(){
var newKlassIndex = ($scope.klassIndex+1)%$scope.klasses.length;
$scope.klassIndex = newKlassIndex;
};
});
View
<body ng-app="ap" ng-controller="con">
<div ng-repeat="klass in klasses">
<div ng-class="klasses[klassIndex]">{{klasses[klassIndex]}}</div>
<button ng-click="changeClass()">Change Class</button>
</div>
</body>
This way new class can be added to $scope.klasses, with new corresponding CSS rule.
Working Demo
http://jsfiddle.net/pWG2S/1267/

Let think about make directive for each section :
<div ng-class="class">{{class}}</div>
<button ng-click="changeClass()">Change Class</button>
Then you can control scope inside each directive and it will be easy for you to extend later.
This is example : http://jsfiddle.net/pWG2S/1271/

Related

changing bootstrap progress bar color based on percentage

I created a progress bar using Bootstrap and want the color to change dynamically based on percentage. So far this is what my code looks like:
<div class="progress" style="height: {{c.options.bar_height}}px;">
<div class="progress-bar progress-bar-striped active {{c.progress_bar_color}}" role="progressbar" aria-valuenow={{c.data.percent_complete}} aria-valuemin="0" aria-valuemax="100" style="width:{{c.data.percent_complete}}; font-size: {{c.options.font_size}};">
{{c.data.percent_complete}}
</div>
</div>
In my client controller, I have set the colors as such:
if(c.data.percent_complete<=50) {
c.progress_bar_color = 'progress-bar-danger';
}
if(c.data.percent_complete>50 && c.data.percent_complete<=75) {
c.progress_bar_color = 'progress-bar-warning';
}
if(c.data.percent_complete>75 && c.data.percent_complete<=99.99) {
c.progress_bar_color = 'progress-bar-primary';
}
if(c.data.percent_complete==100) {
c.progress_bar_color = 'progress-bar-success';
}
So far, the progress bar doesn't change color at all. What am I missing to get this to work?
EDIT
I got rid of my client controller and added a ng-class:
ng-class="{'progress-bar-danger': c.data.percent_complete<'33', 'progress-bar-warning': c.data.percent_complete>='33' && c.data.percent_complete<'66', 'progress-bar-success': c.data.percent_complete>='66'}"
This works for every scenario, EXCEPT when it is 100%. When the bar reaches 100%, for whatever reason, it changes to progress-bar-danger instead of progress-bar-success. Any suggestions how to fix this? Thanks!
Could try using ng-class="c.progress_bar_color" instead
Maybe this working JSFiddle helps :)
I fixed this by using uib-progressbar instead:
My client controller:
var value = c.data.percent_complete;
var type;
if (value <= c.options.danger_threshold) {
type = 'danger';
} else if (value > c.options.danger_threshold && value <= c.options.warning_threshold) {
type = 'warning';
} else if (value > c.options.warning_threshold && value <= c.options.primary_threshold) {
type = 'primary';
} else {
type = 'success';
}
c.percentage_label = value+'%';
c.type = type;
My revised HTML:
<uib-progressbar style="height: {{c.options.bar_height}}px;" class="progress-striped active" value="c.data.percent_complete" type="{{c.type}}">
<div>
<span style="font-size: {{c.options.font_size}};">{{c.percentage_label}}</span>
<i ng-if="c.data.empty.length>0" class="fa fa-info-circle info m-l-xs" popover-placement="{{c.dynamicPopover.placement}}" popover-trigger="mouseenter" uib-popover-template="c.dynamicPopover.templateUrl" popover-title="{{c.data.empty.length}} Required Fields Missing"></i>
</div>
</uib-progressbar>

How to add a class to an element when another element gets a class in angular?

I have a scrollspy directive that adds an ".active" class to a nav item. When the first nav item has the ".active" class I want my header bar to contain a certain class too. Attached is a simplified example, but how can I add ".active" to item 1 by only looking at the classes in item 2. jsfiddle
<div ng-app>
<div ng-controller='ctrl'>
<div id="item1" ng-class="if item2 has class=active then add active class here">Item 1</div>
<div id="item2" ng-class="myVar">Item 2</div>
</div>
//I can't use a scope object I can only look at item 2's classes
<button type="button" ng-click="myVar='active'">Add Class</button>
<button type="button" ng-click="myVar=''">Remove Class</button>
Click here for live demo.
You'll need a directive to interact with the element. I would have the directive watch the element's classes and have it call a function from your controller when the classes change. Then, your controller function can apply the logic specific to your need, which is to set a flag letting another element know how to respond.
angular.module('myApp', [])
.controller('MyCtrl', function($scope) {
$scope.foo = function(classes) {
if (~classes.indexOf('active')) {
$scope.otherItemIsActive = true;
}
};
})
.directive('onClassChange', function() {
return {
scope: {
onClassChange: '='
},
link: function($scope, $element) {
$scope.$watch(function() {
return $element[0].className;
}, function(className) {
$scope.onClassChange(className.split(' '));
});
}
};
})
;

How to applybindings that have different document root

Hi I have the following html:
<div id="div1">
<input id="input1" data-bind="value: inputIn, valueUpdate: 'afterKeydown'" >
// ... more stuff between
</div>
<div id="div2">
<input id="input2" data-bind="value: inputOut">
// .... more stuff between
</div>
My model is this:
function MyModel() {
"use strict";
this.inputIn = ko.observable("");
this.inputOut = ko.computed(function() {
return transformOutput(this.inputIn());
}
}
Applying the bindings:
var myModel = new MyModel();
ko.applyBindings(model, document.getElementById("div2"));
ko.applyBindings(model, document.getElementById("div1"));
I want changes in input 1 to effect input 2. What is wrong? Is their way around this without changing the html. The element are in two different divs and I want the knockout binding to apply to be apply across cross root domain.
Your problem isn't with how you are binding it (although I don't think it's worth the trouble). Your problem is that this isn't what you think it is in the computed property (it's actually window).
Try this:
function MyModel() {
var self = this;
this.inputIn = ko.observable("");
this.inputOut = ko.computed(function () {
return transformOutput(self.inputIn());
});
}
Here's a simple fiddle

How to set div width using ng-style

I am trying to set the div width dynamically using ng-style but it is not applying the style. Here is the code:
<div style="width: 100%;" id="container_fform" ng-controller="custController">
<div style="width: 250px;overflow: scroll;">
<div ng-style="myStyle"> </div>
</div>
</div>
Controller:
var MyApp = angular.module('MyApp', []);
var custController = MyApp.controller('custController', function ($scope) {
$scope.myStyle="width:'900px';background:red";
});
What am I missing?
Fiddle link: Fiddle
The syntax of ng-style is not quite that. It accepts a dictionary of keys (attribute names) and values (the value they should take, an empty string unsets them) rather than only a string. I think what you want is this:
<div ng-style="{ 'width' : width, 'background' : bgColor }"></div>
And then in your controller:
$scope.width = '900px';
$scope.bgColor = 'red';
This preserves the separation of template and the controller: the controller holds the semantic values while the template maps them to the correct attribute name.
ngStyle accepts a map:
$scope.myStyle = {
"width" : "900px",
"background" : "red"
};
Fiddle

Toggle css on ng-click

This is the basic idea of my code:
HTML (jade):
#preferencesBox(ng-click="toggleCustom()")
.glyphicon.glyphicon-heart
CSS:
#preferencesBox.active{
color: #d04f37;
}
Angular:
$scope.check = true;
$scope.toggleCustom = function() {
$scope.check = $scope.check === false ? true: false;
};
I want to add the css color : #d04f37 when the user clicks the parent #preferencesBox. Adding/removing .active is the jQuery way. How should my ng-class or the rest code look like?
You can use an expression inside ng-class that will watch the check variable:
ng-class="{'active' : check}"
When check = true, add class active
Take a look at the next example and apply in Jade:
<header ng-click="click()" ng-class="{'active': active == true}">Hello</header>
Then, in your controller:
$scope.click = function(){
$scope.active = true;
}
I'd say this is simple enough to get you started and add logic for toggling into click() (it's only an if).

Resources