Apologies if this shows how much of a novice I am, but I'd like to know more about dynamic variables and CSS in Vue. I'd like to create a system where each time a button is pressed, the letters of the button label become further apart.
Inside a component is it possible to use a counter script such as:
<script>
export default {
name: 'Counter',
data() {
return {
count: 3,
}
},
methods: {
intrement() {
this.count += 1;
}
}
}
</script>
And then use the count integer value to change CSS text spacing for example?
So that in the template, I could use:
<template>
<header>
<div>
<button class="header_button" style="letter-spacing: `v-bind(count) + ch`;">MYBUTTON</button>
</div>
</header>
</template>
I appreciate this is a strange and specific example, but if anyone could give me some feedback as to why this doesn't work, as well as suggestions on how I could achieve this I'd be super appreciative.
In that case, you can directly use the following
<button :style="`letter-spacing: ${count}ch;`">
Here is a playground.
PS: :style is a shorthand for v-bind:style as explained here.
v-bind for CSS (mixing script + style) is also a thing.
Here, you're only using script + template combo, so an interpolation is enough.
I have been struggling to figure out the best way to dynamically change the background-image attribute in a number of Angular 2 components.
In the following example, I am attempting to set the background-image of a div to an #Input value using [ngStyle] directive:
import {Component, Input} from '#angular/core';
import { User } from '../models';
// exporting type aliases to enforce better type safety (https://github.com/ngrx/example-app)
export type UserInput = User;
#Component({
selector: 'profile-sidenav',
styles: [ `
.profile-image {
background-repeat: no-repeat;
background-position: 50%;
border-radius: 50%;
width: 100px;
height: 100px;
}
`],
template: `
<div class="profile-image" [ngStyle]="{ 'background-image': url({{image}})">
<h3>{{ username }}</h3>
`
})
export class ProfileSidenav {
#Input() user: UserInput;
blankImage: string = '../assets/.../camera.png';
// utilizing "getters" to keep templates clean in 'dumb' components (https://github.com/ngrx/example-app)
get username() {
return this.user.username;
}
get image() {
if (!this.user.image) { return this.cameraImage;
} else { return this.user.image; }
}
I don't think the issue is with the observable, since username displays and doing something like <img *ngIf="image" src="{{ image }}"> renders the image. I have to access the background-image attribute because apparently that is the best way to make a circular image, but in general would like to know how to do this.
EDIT:
My original [ngStyle] declaration had unnecessary curly brackets (ngStyle is a directive that can take a variable), and was missing string tags around url() and image. The correct way is (as answered below) is:
<div class="profile-image" [ngStyle]="{'background-image': 'url(' + image + ')'}"></div>`.
As stated in the original edit, a solution can also be achieved with the Renderer class in Angular 2. I have yet to do it but think there should be a way with setElementStylesor something like that. I will try to post an example but would love if someone else showed me (and others) how to for the time being.
I think that you should use something like that:
<div class="profile-image"
[ngStyle]="{ 'background-image': 'url(' + image + ')'}">
where image is a property of your component.
See this question:
How to add background-image using ngStyle (angular2)?
You don't need to use NgStyle. You can also do this:
[style.background-image]="'url(' + image + ')'"
See more at How to add background-image using ngStyle (angular2)?
redfox05's answer works well since there is no space in the image URL, but by a bit change in code we can make it work again:
<div style.background-image="url('{{image}}')"></div>"
The main reason is simple, you declared a global variable as blankImage but in the template you called image instead of blankImage.
Your ts code variable blankImage
blankImage: string = '../assets/.../camera.png';
Your template code variable image
<div class="profile-image" [ngStyle]="{'background-image': 'url(' + image + ')'}"></div>
that's wrong
I think you should add:
<div class="profile-image" [ngStyle]="{ 'backgroundImage': url({{image}})">
Regards
I'm looking to set the background image of a div dynamically using ng-style. There are a couple of answers, but none work for me.
I've realised that for a simple case as shown below, there's no problem
<li ng-style="{'background-image': 'url({{ image.source }})'}">...</li>
where $scope.image = ... is defined. Or even more straightforward:
<li ng-style="{'background-image': 'url(http://example.com/image.png)'}">...</li>
But supposing you have the following:
<li ng-style="{'background-image': 'url({{ item.image_url }})'}">...</li>
and in your controller:
$scope.item = undefined;
Items.get({id: 1})
.then(function (item) {
$scope.item = item;
});
Item becomes available after the template has been rendered. And I find that angular just sets the background-image to the host url
<li ng-style="{'background-image': 'url({{ item.image_url }})'}" style="background-image: url(http://localhost:3000/);">
</li>
I could use a custom directive for this, but if there's a simple way of getting this to work, I'd prefer this over a directive.
Here's a plunker demonstrating the issue:
http://plnkr.co/edit/5JsK4njQi7Kc3ShUtRIw?p=preview
ng-style already binds the scope variables, so you don't need to add the curly braces, but could simply concat the correct string value:
ng-style="{'background-image': 'url(' + item.image_url + ')' }"
http://plnkr.co/edit/b9htGOTY6LBeHQMQNYXV?p=preview
ng-style="{'background-image': 'url({{item.image_url}})' }"
Plunker
<div ng-if="item.image_url" class="img-div" ng-style="{'background-image': 'url({{item.image_url}})' }"></div>
Use ng-if so when item.image_url get value after that your element is get rendered.
Plunker example
Well, being straight forward the problem is my $scope.$apply() is also not digesting the changes to rerun the translate directive.
I show you the HTML with applied translation directive and jQUERY code to change the class on resize of the windows (client).
HTML for menu:
<div id="navigation" ng-cloak>
<div class="container-fluid">
BRAND NAME
<ul class='main-nav'>
<li ng-class="{'active':activeLink == 'home'}">
<a href="#/">
<span>Home</span>
</a>
</li>
<li ng-class="{'active':activeLink == 'planning'}" data-trigger="hover">
<a href="#" data-toggle="dropdown" class='dropdown-toggle'>
<span>Planning</span>
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<a href="#" data-toggle="dropdown" class='dropdown-toggle'>Goals</a>
<ul class="dropdown-menu">
<li>
{{'TOP_MENU.GOAL_LIST' | translate}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
HERE is the JQuery Code to make it responsive for screen size changes.
function checkLeftNav() {
var $w = $(window),
$content = $("#content"),
$left = $("#left");
if ($w.width() <= 840) {
if (!$left.hasClass("mobile-show")) {
$left.hide();
$("#main").css("margin-left", 0);
}
if ($(".toggle-mobile").length == 0) {
$("#navigation .user").after('<i class="fa fa-bars"></i>');
}
if ($(".mobile-nav").length == 0) {
createSubNav();
}
} else {
if (!$left.is(":visible") && !$left.hasClass("forced-hide") && !$("#content").hasClass("nav-hidden")) {
$left.show();
$("#main").css("margin-left", $left.width());
}
$(".toggle-mobile").remove();
$(".mobile-nav").removeClass("open");
if ($content.hasClass("forced-fixed")) {
$content.removeClass("nav-fixed");
$("#navigation").removeClass("navbar-fixed-top");
}
if ($w.width() < 1200) {
if ($("#navigation .container").length > 0) {
versionFluid();
$('body').addClass("forced-fluid");
}
} else {
if ($('body').hasClass("forced-fluid")) {
versionFixed();
}
}
}
}
Now What my solution was to get he nav element scope on which the jquery is applying class and call the $apply() on its scope. which is not working.
Solution Code:
$(window).resize(function(e) {
checkLeftNav();
// get the scope of element and apply $apply()
var sc = angular.element('.mobile-nav').scope();
sc.$apply();
});
But still when ever the screen size is changed to mobile view less than 840 I can see direct code values instead of translated text in menu like this. and When I change back to screen width more than 840 it shows correct translated text. I am experimenting this on chrome on my pc by resizing. I checked on mobile its not translating there too.
AngularJS provides two-way data binding, not two way everything binding. It's not intended to be used this way. $apply() only looks at the data model - it is the function you call when you want to say "Hey, Angular, I've updated the data model, come have a look!" That is literally its only purpose. There is no method in Angular designed to look at the DOM itself for changes - that's very inefficient and against Angular's philosophies anyway, which is why it ships without jQuery.
You might want to evaluate other frameworks that better support this kind of thing. However, if you really wish to do this you can easily convert it into a proper AngularJS module. The best way is to simply paste all of this code into a controller, and then change the window resize binding to use Angular's $window service, like:
var windowElement = angular.element($window);
windowElement.bind('resize', function() {
// Do my calculations here.
});
With your calculations would you compute the same variables but you would store them in scope variables and then adjust your template to use them. For example, what you're doing with $(".toggle-mobile").remove(); could be replaced by:
if (windowElement.width > 840) {
// Other code here
$scope.isMobile = false;
} else {
$scope.isMobile = false;
}
and in your template:
<i class="fa fa-bars"></i>
Give it a whirl, play with it for a week or two, and you'll never go back to jQuery. It takes a lot of getting used to, but once you do you realize how broken the whole "I'm looking at my template and have no idea what mystery event handlers are bound to all this stuff" concept was to begin with.
Lets say you have an array that is rendered in a ul with an li for each element and a property on the controller called selectedIndex. What would be the best way to add a class to the li with the index selectedIndex in AngularJS?
I am currently duplicating (by hand) the li code and adding the class to one of the li tags and using ng-show and ng-hide to show only one li per index.
If you don't want to put CSS class names into Controller like I do, here is an old trick that I use since pre-v1 days. We can write an expression that evaluates directly to a class name selected, no custom directives are necessary:
ng:class="{true:'selected', false:''}[$index==selectedIndex]"
Please note the old syntax with colon.
There is also a new better way of applying classes conditionally, like:
ng-class="{selected: $index==selectedIndex}"
Angular now supports expressions that return an object. Each property (name) of this object is now considered as a class name and is applied depending on its value.
However these ways are not functionally equal. Here is an example:
ng-class="{admin:'enabled', moderator:'disabled', '':'hidden'}[user.role]"
We could therefore reuse existing CSS classes by basically mapping a model property to a class name and at the same time keep CSS classes out of Controller code.
ng-class supports an expression that must evaluate to either
A string of space-delimited class names, or
An array of class names, or
A map/object of class names to boolean values.
So, using form 3) we can simply write
ng-class="{'selected': $index==selectedIndex}"
See also How do I conditionally apply CSS styles in AngularJS? for a broader answer.
Update: Angular 1.1.5 has added support for a ternary operator, so if that construct is more familiar to you:
ng-class="($index==selectedIndex) ? 'selected' : ''"
My favorite method is using the ternary expression.
ng-class="condition ? 'trueClass' : 'falseClass'"
Note: Incase you're using a older version of Angular you should use this instead,
ng-class="condition && 'trueClass' || 'falseClass'"
I'll add to this, because some of these answers seem out of date. Here's how I do it:
<class="ng-class:isSelected">
Where 'isSelected' is a javascript variable defined within the scoped angular controller.
To more specifically address your question, here's how you might generate a list with that:
HTML
<div ng-controller="ListCtrl">
<li class="ng-class:item.isSelected" ng-repeat="item in list">
{{item.name}}
</li>
</div>
JS
function ListCtrl($scope) {
$scope.list = [
{"name": "Item 1", "isSelected": "active"},
{"name": "Item 2", "isSelected": ""}
]
}
See: http://jsfiddle.net/tTfWM/
See: http://docs.angularjs.org/api/ng.directive:ngClass
Here is a much simpler solution:
function MyControl($scope){
$scope.values = ["a","b","c","d","e","f"];
$scope.selectedIndex = -1;
$scope.toggleSelect = function(ind){
if( ind === $scope.selectedIndex ){
$scope.selectedIndex = -1;
} else{
$scope.selectedIndex = ind;
}
}
$scope.getClass = function(ind){
if( ind === $scope.selectedIndex ){
return "selected";
} else{
return "";
}
}
$scope.getButtonLabel = function(ind){
if( ind === $scope.selectedIndex ){
return "Deselect";
} else{
return "Select";
}
}
}
.selected {
color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<div ng-app ng-controller="MyControl">
<ul>
<li ng-class="getClass($index)" ng-repeat="value in values" >{{value}} <button ng-click="toggleSelect($index)">{{getButtonLabel($index)}}</button></li>
</ul>
<p>Selected: {{selectedIndex}}</p>
</div>
I faced a similar problem recently and decided to just create a conditional filter:
angular.module('myFilters', []).
/**
* "if" filter
* Simple filter useful for conditionally applying CSS classes and decouple
* view from controller
*/
filter('if', function() {
return function(input, value) {
if (typeof(input) === 'string') {
input = [input, ''];
}
return value? input[0] : input[1];
};
});
It takes a single argument, which is either a 2-element array or a string, which gets turned into an array that is appended an empty string as the second element:
<li ng-repeat="item in products | filter:search | orderBy:orderProp |
page:pageNum:pageLength" ng-class="'opened'|if:isOpen(item)">
...
</li>
If you want to go beyond binary evaluation and keep your CSS out of your controller you can implement a simple filter that evaluates the input against a map object:
angular.module('myApp.filters, [])
.filter('switch', function () {
return function (input, map) {
return map[input] || '';
};
});
This allows you to write your markup like this:
<div ng-class="muppets.star|switch:{'Kermit':'green', 'Miss Piggy': 'pink', 'Animal': 'loud'}">
...
</div>
The was I recently did that was doing this:
<input type="password" placeholder="Enter your password"
ng-class="{true: 'form-control isActive', false: 'isNotActive'}[isShowing]">
The isShowing value is a value that is located on my controller that gets toggled with the click of a button and the parts between the single parenthesis are classes I created in my css file.
EDIT: I would also like to add that codeschool.com has a free course that is sponsored by google on AngularJS that goes over all of this stuff and then some. There is no need to pay for anything, just signup for an account and get going!
Best of luck to you all!
Ternary operator has just been added to angular parser in 1.1.5.
So the simplest way to do this is now :
ng:class="($index==selectedIndex)? 'selected' : ''"
We can make a function to manage return class with condition
<script>
angular.module('myapp', [])
.controller('ExampleController', ['$scope', function ($scope) {
$scope.MyColors = ['It is Red', 'It is Yellow', 'It is Blue', 'It is Green', 'It is Gray'];
$scope.getClass = function (strValue) {
switch(strValue) {
case "It is Red":return "Red";break;
case "It is Yellow":return "Yellow";break;
case "It is Blue":return "Blue";break;
case "It is Green":return "Green";break;
case "It is Gray":return "Gray";break;
}
}
}]);
</script>
And then
<body ng-app="myapp" ng-controller="ExampleController">
<h2>AngularJS ng-class if example</h2>
<ul >
<li ng-repeat="icolor in MyColors" >
<p ng-class="[getClass(icolor), 'b']">{{icolor}}</p>
</li>
</ul>
<hr/>
<p>Other way using : ng-class="{'class1' : expression1, 'class2' : expression2,'class3':expression2,...}"</p>
<ul>
<li ng-repeat="icolor in MyColors">
<p ng-class="{'Red':icolor=='It is Red','Yellow':icolor=='It is Yellow','Blue':icolor=='It is Blue','Green':icolor=='It is Green','Gray':icolor=='It is Gray'}" class="b">{{icolor}}</p>
</li>
</ul>
You can refer to full code page at ng-class if example
I am new to Angular but have found this to solve my issue:
<i class="icon-download" ng-click="showDetails = ! showDetails" ng-class="{'icon-upload': showDetails}"></i>
This will conditionally apply a class based on a var.
It starts off with a icon-download as a default, the using ng-class, I check the status of showDetails if true/false and apply class icon-upload. Its working great.
Hope it helps.
This works like a charm ;)
<ul class="nav nav-pills" ng-init="selectedType = 'return'">
<li role="presentation" ng-class="{'active':selectedType === 'return'}"
ng-click="selectedType = 'return'"><a href="#return">return
</a></li>
<li role="presentation" ng-class="{'active':selectedType === 'oneway'}"
ng-click="selectedType = 'oneway'"><a href="#oneway">oneway
</a></li>
</ul>
This will probably get downvoted to oblivion, but here is how I used 1.1.5's ternary operators to switch classes depending on whether a row in a table is the first, middle or last -- except if there is only one row in the table:
<span class="attribute-row" ng-class="(restaurant.Attributes.length === 1) || ($first ? 'attribute-first-row': false || $middle ? 'attribute-middle-row': false || $last ? 'attribute-last-row': false)">
</span>
This is in my work multiple conditionally judge:
<li ng-repeat='eOption in exam.examOptions' ng-class="exam.examTitle.ANSWER_COM==exam.examTitle.RIGHT_ANSWER?(eOption.eoSequence==exam.examTitle.ANSWER_COM?'right':''):eOption.eoSequence==exam.examTitle.ANSWER_COM?'wrong':eOption.eoSequence==exam.examTitle.RIGHT_ANSWER?'right':''">
<strong>{{eOption.eoSequence}}</strong> |
<span ng-bind-html="eOption.eoName | to_trusted">2020 å…ƒ</span>
</li>
Here is another option that works well when ng-class can't be used (for example when styling SVG):
ng-attr-class="{{someBoolean && 'class-when-true' || 'class-when-false' }}"
(I think you need to be on latest unstable Angular to use ng-attr-, I'm currently on 1.1.4)
well i would suggest you to check condition in your controller with a function returning true or false .
<div class="week-wrap" ng-class="{today: getTodayForHighLight(todayDate, day.date)}">{{day.date}}</div>
and in your controller check the condition
$scope.getTodayForHighLight = function(today, date){
return (today == date);
}
partial
<div class="col-md-4 text-right">
<a ng-class="campaign_range === 'thismonth' ? 'btn btn-blue' : 'btn btn-link'" href="#" ng-click='change_range("thismonth")'>This Month</a>
<a ng-class="campaign_range === 'all' ? 'btn btn-blue' : 'btn btn-link'" href="#" ng-click='change_range("all")'>All Time</a>
</div>
controller
$scope.campaign_range = "all";
$scope.change_range = function(range) {
if (range === "all")
{
$scope.campaign_range = "all"
}
else
{
$scope.campaign_range = "thismonth"
}
};
If you are using angular pre v1.1.5 (i.e. no ternary operator) and you still want an equivalent way to set a value in both conditions you can do something like this:
ng-class="{'class1':item.isReadOnly == false, 'class2':item.isReadOnly == true}"
If you having a common class that is applied to many elements you can create a custom directive that will add that class like ng-show/ng-hide.
This directive will add the class 'active' to the button if it's clicked
module.directive('ngActive', ['$animate', function($animate) {
return function(scope, element, attr) {
scope.$watch(attr.ngActive, function ngActiveWatchAction(value){
$animate[value ? 'addClass' : 'removeClass'](element, 'active');
});
};
}]);
More info
Just adding something that worked for me today, after much searching...
<div class="form-group" ng-class="{true: 'has-error'}[ctrl.submitted && myForm.myField.$error.required]">
Hope this assists in your successful development.
=)
Undocumented Expression Syntax : Great Website Link... =)
Check this.
The infamous AngularJS if|else statement!!!
When I started using Angularjs, I was a bit surprised that I couldn’t find an if/else statement.
So I was working on a project and I noticed that when using the if/else statement, the condition shows while loading.
You can use ng-cloak to fix this.
<div class="ng-cloak">
<p ng-show="statement">Show this line</span>
<p ng-hide="statement">Show this line instead</span>
</div>
.ng-cloak { display: none }
Thanks amadou
You can use this npm package. It handles everything and has options for static and conditional classes based on a variable or a function.
// Support for string arguments
getClassNames('class1', 'class2');
// support for Object
getClassNames({class1: true, class2 : false});
// support for all type of data
getClassNames('class1', 'class2', ['class3', 'class4'], {
class5 : function() { return false; },
class6 : function() { return true; }
});
<div className={getClassNames({class1: true, class2 : false})} />
I understand this question id for angular, but if anyone is using React or a React-Based Framework (Amplify, NextJS, Serverless, etc.) The solution is significantly easier. The most performant way is with a ternary operator like so:
<div className={condition ? "classnameiftrue" : "classnameiffalse"}>
You can use this strategy to animate the tree if using useState() as each time the state changes it will reload that conditional with the new value.