Manipulating inline style with angular does not work in IE - html

I wanted to set the position of a div based on the return value of a function in an angular controller
The following works fine in FireFox and in chrome but in Internet explorer {{position($index)}}% is interpreted as a literal string value and therefore has no effect
<div ng-repeat="item in items" style="left:{{position($index)}}%"></div>
Here is an example of the issue:
var app = angular.module('app', []);
app.controller('controller', function($scope) {
$scope.items=[1,2,3,4,5,6,7,8,9,10];
$scope.position=function(i){
var percent =[5,10,15,20,25,30,35,40,45,50,55,60,65,70];
return percent[i+1];
}
});
And here is a Fiddle to demonstrate
Does anyone have suggestions on how to rectify?

You must use ng-style instead of style, otherwise some browsers like IE will remove invalid style attribute values (presence of {{}} etc makes it invalid) before even angular has a chance to render it. When you use ng-style angular will calculate the expression and add the inline style attributes to it.
<div ng-repeat="item in items" ng-style="{left: position($index) + '%'}"></div>
Since you are anyways calculating the position you could as well add % from the position and send it. Also remember that calling a function in ng-repeat will invoke the function every digest cycle, so you may want to be careful not to do too much intensive operations inside the method.
<div ng-repeat="item in items" ng-style="{left: position($index)}">{{item}}</div>
and return
return percent[i+1] + "%";
Demo

If you want to use angular binding expression {{}} just like normal style attribute like style="width:{{someScopeVar}}",
use ng-attr-style and it will work perfectly IE (and obviously other smarter ones) :)
check my jsFiddle ... Checked with Angular JS 1.4.8
here I have shown the usage of style, ng-style and ng-attr-style
THE HTML
<div ng-app="app">
<div ng-controller="controller">
<div style="background:{{bgColor}}">
This will NOT get colored in IE
</div>
<div ng-attr-style="background:{{bgColor}}">
But this WILL get colored in IE
</div>
<div ng-style="styleObject">
And so is this... as this uses a json object and gives that to ng-style
</div>
</div>
</div>
THE JS
var app = angular.module('app', []);
app.controller('controller', function($scope) {
$scope.bgColor = "yellow";
$scope.styleObject = {"background": "yellow"};
});

Yes, ng-style will work to resolve this problem. You can use conditionally style using ternary operator.
HTML:
<div ng-style="{'display':showInfo?'block':'none'}">
</div>

Related

Angular variable output if/else HTML output not working

I'm confused. I'm trying to check in a loop if the outputted key is a mail key, if yes, I want to wrap the output into a <a> tag to make the email clickable. Somehow it's not working and it's printing the whole content inside the div:
<div>{{contactInfo.key === 'mail_outline' ? '' + contactInfo.value + '' : contactInfo.value}}</div>
Current result on the page:
{{contactInfo.key === 'mail_outline' ? '' + contactInfo.value + '' : contactInfo.value}}
I'm not sure if I understood the whole thing correctly. I'm coming from PHP and there I can do something like this. Can someone please explain me my issue?
If you surround the html elements inside the div with quotes like you did, you are telling angular that the divcontent is actually a text value. So it will end up displaying your condition as text.
You can add dynamic html by binding to innerHtml property like suggested, however I find it cleaner to keep display logic in the template using one of the options below. Besides, they will avoid the extra overhead of calling a function every round of change detection
*ngIf
<div >
<a *ngIf="contactInfo.key === 'mail_outline'" href="{{contactInfo.value}}">{{contactInfo.value}}</a>
<ng-container *ngIf="contactInfo.key !== 'mail_outline'">{{contactInfo.value}}</ng-container>
</div>
Or use *ngSwitch, which will be more adequate if you've got several different cases
<div [ngSwitch]="contactInfo.key">
<a *ngSwitchCase="'mail_outline'" href="{{contactInfo.value}}">{{contactInfo.value}}</a>
<ng-container *ngSwitchDefault>{{contactInfo.value}}</ng-container>
</div>
Use angular Html binding. Update your html
<div [innerHtml]="getLink()"></div>
In your typescript
getLink(){
if(this.contactInfo.key === 'mail_outline')
{
return `<a href='${this.contactInfo.value}'>${this.contactInfo.value}</a>`;
}
else
{
return this.contactInfo.value;
}
}
Thanks.

Dynamic Inline CSS using AngularJS

I have an angular app and need to apply some CSS styles on a page, at runtime.
Solution using ng-style is not scalable:
I am aware that for specific (known) items, this can easily be done using the ng-style directive e.g.:
<div id="mydiv" ng-style="{color: bgColor}">ABCD</div>
However, this technique cannot be applied to all the <a> or <p> tags on the page. How does one apply a dynamic style based on an angular scope variable to ALL instances of a tag on the page?
Something like the following would be ideal:
<style>
.in3_counter {color: {{settings.in3Color}};}
.in4_counter {color: {{settings.in4Color}};}
</style>
Update: The value of the css scope variables isn't predetermined, so I we don't know what colors would be applied to the elements as the variables are set at runtime (e.g. with color picker).
Any suggestions?
Check the following example:
var COLOR_CTRL = function($scope, $sce) {
$scope.changeColor = function(color) {
$scope.style = $sce.trustAsHtml('a, p {color: ' + color + '}');
};
$scope.changeColor('#000');
};
var app = angular.module('app', []);
app.controller('ColorCtrl', ['$scope', '$sce', COLOR_CTRL]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js"></script>
<div ng-controller="ColorCtrl" ng-app="app">
anchor
<p>paragraph</p>
<div>
<button ng-click="changeColor('#f00')">red</button>
<button ng-click="changeColor('#0f0')">green</button>
<button ng-click="changeColor('#00f')">blue</button>
</div>
<style data-ng-bind-html="style"></style>
</div>

Span inside div doesn't apply ng-style

i am trying to Append spans in a div. Below is my div code
<div
id="paragraph"
class="paragraph"
name="paragraph">
</div>
This is code i am implementing in my Controller
$scope.style_Text = {color:'#F00'};
for(var i = 0; i< $scope.paragraph.length; i++)
{
var span = "<span ng-style='style_Text' id='c"+i+"'>"+$scope.paragraph[i]+"</span>";
$( ".paragraph" ).append($(span));
console.log(span);
}
Spans are added in the div, but style is not applied. When i copy the span from console and place it above div. This span is working fine. Style is applied on it.
I have tried putting style='color:red;' instead of ng-style, It also works.
Please help how to use ng-style here. Thank
What for u doing this? Thats bad pattern.
Your HTML:
<div
id="paragraph"
class="paragraph"
name="paragraph">
<span ng-repeat="elem in list">{{ elem.xxx }}</span>
</div>
In controller just add objects in your $scope.list after some action
$scope.addToList = function() {
$scope.list.push({...});
}
And angular add them to DOM inside your div tag.
If you use not angular event model for refresh DOM use $scope.$apply().
Do not mix jQuery to Angular, you really not need to
Do all the DOM manipulation in directives!
Now to your question, if you really want to it your way
You wanted this $scope.style_Text = {color:'#F00'}; to be a string I guess, so $scope.style_Text = '{color:\'#F00\'};' and then var span = "<span ng-style=" + $scope.style_Text + " id='c"+i+"'>"+$scope.paragraph[i]+"</span>";
But really please do a directive
Edit: in such a case like this, what is the point of using ng-style and not style itself?

DOM manipulation by angularjs direction

I read that Angularjs directives require a different approach than jquery. I am new to angularjs, so it will be great if somebody can explain how to use directives for this simple example. If you click on bottom div, then it moves (re-parent) the top image to the bottom div. I could add this jquery code on ng-click... but is there a better way?
JQUERY INTENT:
$("#bottom").click(function(){
$("#myimage").appendTo("#bottom");
});
ANGULARJS:
<div ng-app="myapp">
<div data-ng-controller="mycontroller">
<div id="top" style="background-color:red;width:200px;height:200px">
<img id="myimage" src="//placehold.it/150x150">
</div>
<div id="bottom" style="background-color:green;width:200px;height:200px">
</div>
</div>
</div>
Instead of listening for a click in jQuery, you can use Angular's ng-click directive to specify a function to call when the element is clicked and you can use the ng-if directive to add/remove the image, for example...
<div ng-click="appendImage()" id="bottom" style="background-color:green;width:200px;height:200px">
<img ng-if="showImage" id="myimage" src="//placehold.it/150x150">
</div>
Then in your controller...
angular.controller('myController', function ($scope) {
$scope.showImage = false;
$scope.appendImage = function (event) {
$scope.showImage = true;
};
});
A key difference between plain jQuery and Angular is that in jQuery you have to write code to manipulate the DOM yourself (like appending the image). If you use directives properly in Angular, you simply make changes to the $scope and directives will update the DOM for you automatically

ng-bind-html directive removes style attribute when renders

When I write
<div ng-bind-html="slideContent"></div>
where
this.$scope.slideContent =
this.$sce.trustAsHtml("<img src='1.jpg' style='width: 231px'></img>");
angular removes style attribute, so image has initial size.
What do you think? How I can avoid this?
Thanks!
Note that ng-bind-html-unsafe has been removed from Angular.
I would rather create a filter, instead of adding a function to scope in order to avoid scopes pollution and improve the code reusability:
app.filter('unsafe', ['$sce', function ($sce) {
return function (input) {
return $sce.trustAsHtml(input);
}
}]);
There is no need to write anything in the scope, just add the filter on the template:
<div ng-bind-html="resultList.section | unsafe"></div>
use ng-bind-html="trustedHtml(resultList.section)" in html tag
and put this function controller
$scope.trustedHtml = function (plainText) {
return $sce.trustAsHtml(plainText);
}
<div ng-bind-html="trustedHtml(resultList.section)"></div>
use ng-bind-html-unsafe instead. but be careful to not use it with input provided by users.