ng-bind-html directive removes style attribute when renders - html

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.

Related

How to use ngIf to choose diffrent selector in html in an angular app

I have a question about how to use ngIF in HTML code to choose different selector.
I show my code as follow:
in HTML Code:
<a class="style" (click)=clickFunction() (keyup.Enter)=ke()>
<div>
content
</div>
</a>
this is html is in a shared component,
I want to use this shared component into the other component with input parameter noClickAndKeyEnter=true |false
so in this case I should change html code as follow:
<a class="stype" (click)="noClickAndKeyEnter ? clickFunction(): ''" (keyup.Enter)="noClickAndKeyEnter ? ke() :''">
<div>
content
</div>
</a>
My question is, is there also the easy way to resolve my question, that I do not write all place with noClickAndKeyEnter ? :
any solutions?
There are multiple ways you can do this. The simplest could be:
clickFunction(){
if(this.noClickAndKeyEnter){
// execute code here
} else {
// just return or whatever you want here
}
}
You can use the callback pattern!
ts
conditionallyExecute(callback: Function, ...params) {
if(this.noClickAndKeyEnter) {
callback(params)
}
}
html
<a class="stype" (click)="conditionallyExecute(clickFunction, 1, 2)" (keyup.Enter)="conditionallyExecute(ke)">
<div>
content
</div>
</a>
Just a simple guard in your functions
clickFunction() {
if (!this.noClickAndKeyEnter) return;
...
}
ke() {
if (!this.noClickAndKeyEnter) return;
...
}
But by the name of noClickAndKeyEnter I think you might have the true / false values backwards.

How can I identify which classes and id are been used in a html document?

Im trying to remove unused classes and id's in my site. Is there a function that I can use in the browser's JavaScript console (or other methods) to filter out the used/unused classes and elements.
Thanks in advance.
Something like this could work:
let classList = ["class1","class2","class3","class4","class5"];
classList.forEach(cl=>checkClasses(cl));
function checkClasses(classToCheck) {
if(document.querySelector('.'+classToCheck)){
console.log(classToCheck+' is being used');
}else {
console.log(classToCheck+' is not being used');
}
}
<div class="class1"></div>
<div class="class2"></div>
<div class="class4"></div>
<div class="class5"></div>

Replace element with razor textarea

I want to take a tag and replace with a #Html.textarea() razor html helper but it doesn't look as if JQuery can replace DOM elements with html helpers. How do I go about this?
using(#Html.BeginForm())
{
<a id="clickme">Edit</a>
<div>#Model.username</div>
}
How can I replace this div with #Html.Textarea ? JQuery could do it with div and input tags.
jQuery cannot replace a tag with #Html.TextArea() !
The TextArea helper method is a C# method, which gets executed when razor tries to render the view. This happens in your web server. jQuery is a client side library and anything you do with jQuery happens at client side, in your browser.
But all these helper methods ultimately generate some HTML for DOM elements. That means, you can use jQuery to manipulate visibility of that.
If you are trying to do something like an inline edit, you can use a script like this , to start with
First, render the text area along with your label div, but have it hidden initially. Also wrap the label,edit link and the hidden input inside a container div which we can use later to help with our jQuery selectors.
#using (#Html.BeginForm())
{
<div class="edit-item">
Edit
<div class="edit-label">#Model.FirstName</div>
#Html.TextAreaFor(a => a.FirstName,
new { style = "display:none;", #class = "edit-text" })
</div>
<div class="edit-item">
Edit
<div class="edit-label">#Model.UserName</div>
#Html.TextAreaFor(a => a.UserName,
new { style = "display:none;", #class = "edit-text" })
</div>
}
Now when the user clicks edit, you have to toggle the visibility of the label and hidden input and update the value of label after user done editing the value in the input element.
$(function () {
$("a[data-mode]").click(function (e) {
e.preventDefault();
var _this = $(this);
var c = _this.closest(".edit-item");
c.find(".edit-text").toggle();
c.find(".edit-label").toggle();
if (_this.attr("data-mode") === 'label') {
_this.attr("data-mode", 'edit');
_this.text("done");
} else if (_this.data("mode") === 'edit') {
c.find(".edit-label").text(c.find(".edit-text").val());
_this.text("edit");
_this.attr("data-mode", 'label');
}
});
});
This is a head start. You can optimize this code as needed.
Here is a working jsfiddle for your reference

Angular conditional container element

I have a large chunk of HTML in an ng-repeat that for certain elements has a container element and for others it does not. I'm currently achieving this with two ng-ifs:
<strike ng-if="elem.flag">
… <!-- several lines of directives handling other branching cases -->
</strike>
<div ng-if="!elem.flag">
… <!-- those same several lines copied-and-pasted -->
</div>
While this works, it means I have to remember copy-and-paste any edits, which is not only inelegant but also prone to bugs. Ideally, I could DRY this up with something like the following (inspired by ng-class syntax):
<ng-element="{'strike':flag, 'div':(!flag)}">
… <!-- lots of code just once! -->
</ng-element>
Is there any way to achieve a similarly non-repetitive solution for this case?
You can make such directive yourself.
You can use ng-include to include the same content into both elements.
Assuming the effect you desire is to have the text within your tag be striked through based on the condition of the elem.flag:
You could simply use the ng-class as follows
angular.module('ngClassExample', [])
.controller('elemController', Controller1);
function Controller1() {
vm = this;
vm.flag = true;
vm.clickItem = clickItem
function clickItem() {
// Toggle the flag
vm.flag = !vm.flag;
};
}
.strikethrough{
text-decoration: line-through
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='ngClassExample' ng-controller="elemController as elem">
<div ng-class="{strikethrough: elem.flag}" ng-click="elem.clickItem()">
element content should be sticked through: {{elem.flag}}
</div>
</div>
You can do it with a directive
module.directive('myFlag', function() {
var tmpl1 = '<strike>...</strike>';
var tmpl2 = '<div>...</div>';
return {
scope: {
myFlag: '='
},
link: function(scope, element) {
element.html(''); // empty element
if (scope.myFlag) {
element.append(tmpl1);
} else {
element.append(tmpl2);
}
}
};
});
And you just use it like:
<div ng-repeat="item in list" my-flag="item.flag"></div>
You could create a directive which will transclude the content based on condition. For tranclusion you could use ng-transclude drirective, in directive template. Also you need to set transclude: true.
HTML
<my-directive ng-attr-element="{{elem.flag ? 'strike': 'div'}}">
<div> Common content</div>
</my-directive>
Directive
app.directive('myDirective', function($parse, $interpolate) {
return {
transclude: true,
replace: false, //will replace the directive element with directive template
template: function(element, attrs) {
//this seems hacky statement
var result = $interpolate(attrs.element)(element.parent().scope);
var html = '<'+ result + ' ng-transclude></'+result+'>';
return html;
}
}
})
Demo Plunkr
You can also use ng-transclude :
Create your directive :
<container-directive strike="flag">
<!-- your html here-->
</container-directive>
Then in your directive do something like :
<strike ng-if="strike">
<ng-transclude></ng-transclude>
</strike>
<div ng-if="!strike">
<ng-transclude></ng-transclude>
</div>

Manipulating inline style with angular does not work in IE

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>