ng-class doesn't set image-background after rendering - css

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

Related

Vue JS CSS style binding

I am trying to bind CSS styling to vuejs tags. I dont seem to be able to get it working.
Below is the code which i am trying. Can anyone help me out with this? I am not able to get the Styling to work. I am trying this as well as binding based on conditional. Both doesnt seem to work. Can anyone help me with this? I have tried all the ways i could find on stackoverflow, none of them seem to work for me. Can any one help me if i am doing something wrong?
<b-table
class="PatientTable"
borderless
hover
v-on:row-clicked="redirectToPatientView"
:items="users"
:fields="fields"
:current-page="currentPage"
:per-page="perPage"
id="tableData"
>
<template v-for="key1 in fields" v-slot:[`cell(${key1})`]="{ value }" id="tableData" >
<b class="patientData" id="tableData" v-bind:key="key1" v-bind:style="'{font-size:200px;}'">{{ value }}</b>
</template>
When you bind a style, pass in an object instead of a string of an object.
<!-- Instead of: -->
<b :style="'{font-size:200px;}'">{{ value }}</b>
<!-- Do: -->
<b :style="{ 'font-size' : '200px' }">{{ value }}</b>
Notice that, in the second line, the object is placed directly into the double-quotes, without its own set of single-quotes. The contents of those double-quotes are straight up JavaScript, so you don't have to escape the object in them. What you're essentially trying to do is along these lines:
<b :style="styleBinding">{{ value }}</b>
<script>
export default {
data: function() {
return {
styleBinding: {
'font-size': '200px',
'margin-top': '5em',
'other-css-property': 'value'
}
}
}
}
</script>
It's just that, since you're only using a single property, it's a little cleaner to do in-line in the template.
use :class binding instead?
<component :class="{'your-classname' : condition}">
Since inline styling is not really advisable. https://v2.vuejs.org/v2/guide/class-and-style.html

How to use variable in [ngStyle] in angular?

I want to change position depends on some events.
For example at the begining space from top should be 100px, but after button click should be 0px
<mat-list-item class="menu-item disabled " disableRipple (click)="toggleSubmenu($event)">
<h3 matLine class="menu-item-text">Orchestration</h3>
</mat-list-item>
I want to code some similar to
<mat-list-item class="menu-item disabled " disableRipple (click)="toggleSubmenu($event)" [ngStyle]={top: myVarilable+'px'}>
<h3 matLine class="menu-item-text">Orchestration</h3>
</mat-list-item>
but it doesnt work for me. Do you have some ideas to solve it?
I am not sure if is what you are looking for but you can pass an Object in the ngStyle, so you can use a function that returns a dynamically generated object.
Something like that.
HTML
<p [ngStyle]="setMyStyles()">
You say tomato, I say tomato
</p>
Component
setMyStyles() {
let styles = {
'top': this.user.myVarilable + 'px',
};
return styles;
}
You can do this very simply.
[ngStyle]="{'top.px': myVarilable}"
Otherwise:
[style.top.px]="myVarilable"
<div [ngStyle]="{'margin-top': !clicked ? '0px' : '100px'}"></div>
I fixed by adding below code on HTML and ts files.
HTML :
<div [ngStyle]="getStyles()">
TS:
getStyles(): void {
const myStyles = {
'background': 'red,
};
return myStyles;
}
Hope this will work fine.
Upgrading to Angular v9 isn't a Option for my Project. So this works:
<div [style]="color">...</div>
color = this.sanitizer.bypassSecurityTrustStyle('--someKey: ' + someVariable);
example 2:
[style]="colorTest(progressPercentageValueoutOfTotal, progressColor)"
colorTest(progressPercentageValueoutOfTotal, progressColor) {
return this.sanitizer.bypassSecurityTrustStyle('--percent: ' + progressPercentageValueoutOfTotal + '; stroke:' + progressColor);
}
I figured out, that it doesn't work if any other styles were set via [style.anyKey] or [ngStyle], so i had to create a container wich only contains the variable. 🎉

Why does riot.js break css?

In order to learn riot.js I started from well-known bootstrap navbar example. Then I added my custom tag using riot.js:
<script type="riot/tag">
<menu-item>
<li><a href={this.href}><yield/></a></li>
this.href = opts.href
</menu-item>
</script>
<script src="https://cdn.jsdelivr.net/g/riot#2.2(riot.min.js+compiler.min.js)"></script>
<script>
riot.mount('*')
</script>
Finally I tried to use my new tag, replacing
<li>JavaScript</li>
by
<menu-item href="http://getbootstrap.com/javascript">JavaScript</menu-item>
Result is broken. Why? (original non-broken example can be found here: jsfiddle.net/0hp9pwpu)
Your riot tag markup is inserted into your riot tag i.e. what happens is
ul
li
from your working example is actually
ul
menu-item
li
in your non-working example. Since bootstrap styles the navigation items expecting a certain hierarchy, your result is broken.
This was raised as an issue (https://github.com/riot/riot/issues/295) and closed using https://github.com/riot/riot/pull/569 i.e. instead of using the riot tags directly there is an option to add the riot tag as an attribute. So something like
<li riot-tag="menu-item" href="http://getbootstrap.com/javascript">JavaScript</li>
Admittedly, it is not as semantic
Fiddle - http://jsfiddle.net/86khqhwu/
Bootstrap is not adapted for use with Riot.js
Your resulted html is :
<menu-item href="http://getbootstrap.com/javascript">
<li>
JavaScript
</li>
</menu-item>
Bootstrap css is broken ...
Perhaps not so elegant, but in riot 2.3.13 I'm using something like this in a .tag file:
<menu-bar>
<ul list="<yield/>">
<li each={ item in items }>
{ titles[item] }
</li>
</ul>
<script>
this.titles = {
inventario: 'Inventario',
resguardos: 'Resguardos',
catalogos: 'Catálogos',
reportes: 'Reportes',
configurar: 'Configurar',
utilidades: 'Utilidades'
}
this.items = null
this.on('mount', function () {
var el = this.root.querySelector('ul')
this.items = el.getAttribute('list').trim().split(/,\s?/)
el.removeAttribute('list')
this.update()
})
</script>
</menu-bar>
Now, in the HTML page:
<menu-bar>
inventario,resguardos,catalogos,reportes
</menu-bar>
Works.

AngularJs translation directive stop working when I change div class using jquery

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.

What is the best way to conditionally apply a class?

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.

Resources