HTML string not binded with angular [duplicate] - angularjs

This question already has answers here:
ng-bind-html doesnt work for Input tags
(3 answers)
Closed 5 years ago.
<!DOCTYPE html
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<p ng-bind-html="myText"></p>
</div>
<script>
var app = angular.module("myApp", ['ngSanitize']);
app.controller("myCtrl", function($scope) {
$scope.myText = "<input type='text' value='here'>";
});
</script>
<p><b>Note:</b> This example includes the "angular-sanitize.js",
which has functions for removing potentially dangerous tokens from the HTML.</p>
</body>
</html>
I'm new to angular as well. I could not bind the html text to the angular view. Any suggestions could help.

You shoud use $sce.trustAsHtml() like this
$scope.myText=$sce.trustAsHtml("<input type='text' value='here'>")
Like this fiddle
but then you cannot bind scope variables to your html so best way is writing a directive which can be replace with ng-bind-html-unsafe
something like
.directive('bindUnsafeHtml', ['$compile', function ($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
// watch the 'bindUnsafeHtml' expression for changes
return scope.$eval(attrs.bindUnsafeHtml);
},
function(value) {
// when the 'bindUnsafeHtml' expression changes
// assign it into the current DOM
element.html(value);
// compile the new DOM and link it to the current
// scope.
// NOTE: we only compile .childNodes so that
// we don't get into infinite loop compiling ourselves
$compile(element.contents())(scope);
}
);
};
}])
working fiddle

Related

ui-sref not working properly when anchor tag is loaded from properties file

Entry in properties file
MYKEY= <a ui-sref="mystate.state">Go to my page using state</a> and <a href="/#/mypage/page">Go to my page using link/a>
I have fetched this key from properties file & applied $sce.trustAsHtml() on it and used in html. I could see link for Go to my page using link but Go to my page using state not working properly as it has ui-sref tag. Can someone please specify reason why it's not working and solution for this.
Note : ui-sref is working properly in my project when it's directly used in html.
It may be because the content is not compiled, hence ui-sref is not working.
I found the below directive which compiles and inserts html code, please check if this solves your issue!
The Directive was got from this SO Answer
var app = angular.module('myApp', []);
app.controller('MyController', function MyController($scope) {
$scope.test = function() {
console.log("it works!");
}
$scope.html = '<a ui-sref="mystate.state">Go to my page using state</a> and Go to my page using link<button ng-click="test()">click</button>{{asdf}}';
});
app.directive('compile', ['$compile', function ($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
// watch the 'compile' expression for changes
return scope.$eval(attrs.compile);
},
function(value) {
// when the 'compile' expression changes
// assign it into the current DOM
element.html(value);
// compile the new DOM and link it to the current
// scope.
// NOTE: we only compile .childNodes so that
// we don't get into infinite loop compiling ourselves
$compile(element.contents())(scope);
}
);
};
}])
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-controller='MyController' ng-app="myApp">
<div compile="html"></div>
</div>

AngulaJs ng-click in expression html [duplicate]

This question already has answers here:
How to make ng-bind-html compile angularjs code
(8 answers)
Closed 3 years ago.
I am displaying HTML in a AngularJS expression.
In My HTML
<div ng-bind-html="myText"></div>
And In My Controller
$scope.myText = $sce.trustAsHtml("<div class='my-style' ng-click='onClick(10)'>click me</div>");
$scope.onClick = function(value)
{
console.log("onClick: value:"+value);
}
But I am not able to get the click event
UPDATE
In one of the question I see it has be described about how to add HTML tags in the text or how to compile HTML. But my question is related to how to get ng-click event from the complied HTML. I don't see any of the answers providing this solution.
Sorry for again writing the code :
First give a unique id to your div :
<div id="test"></div>
Then Change that code to below one:
var myText = "<div class='my-style' ng-click='onClick(10)'>click me</div>";
var element = angular.element(document.querySelector('#test'));
var generated = element.html(myText);
$compile(generated.contents())($scope);
This will manage your code to work. cheers!
Use directive to implement this functionality. Check demo here http://plnkr.co/edit/tTgVCMt7JqvaQOrjhLLL?p=preview
JS:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.testClick = function(value) {
alert("onClick: value:"+value);
};
});
app.directive("clickDynamic", function(){
return {
template:"<div class='my-style' ng-click='testClick(10)'>click me</div>"
};
});
HTML:
<body ng-controller="MainCtrl">
<div click-dynamic></div>
</body>
I have append the html using id or class
var add = angular.element( document.querySelector( '#updatechoose' ) );
add.append('<div class="form-group" ng-repeat="updatedata in getdata">'+
'<div>'+
'<input type="file" id="imgupload" ng-model="attachment" imgepath="{{updatedata.imagepath}}" imgname="{{updatedata.imagename}}" name="file[]" style="padding-left: 15px;" class="imgupload col-md-4 cropit-image-input" />'+
'<i class="glyphicon glyphicon-trash" **ng-click="remove()"**></i>'+
'</div>'+
'</div>');
One solution is to use plain javascript and get the scope. This way you can call your inside methods.
<div ng-bind-html="myText"></div>
$scope.myText = $sce.trustAsHtml( '<div class="button" onClick="var scope = angular.element(this).scope();scope.testClick(10);">click me</div>' );
Please note that I'm using onClick instead of ng-click, then I get the scope, this way I can call the inner methods.
It's a dirty solution, but maybe it can help you.
I've added a snippet, which shows an implementation via a directive and the $compile service.
angular.module('TestApp', [])
.directive('compileDir', function($compile) {
return {
restrict: 'E',
scope: {
dynTpl: '='
},
template: 'Num clicked: {{numClicked}}',
link: function(scope, elem) {
scope.numClicked = 0;
scope.click = function() {
scope.numClicked++;
};
var tpl = $compile(scope.dynTpl)(scope);
elem.append(tpl);
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.12/angular.min.js"></script>
<div ng-app="TestApp">
<compile-dir dyn-tpl="'<button ng-click=\'click()\'>Click</button>'"></compile-dir>
</div>

AngularJS: Can't call onClick() when using ng-bind-html [duplicate]

I've included a Plunker here: http://plnkr.co/edit/4vqV8toHo0vNjtfICtzI?p=preview
I'm trying to add a button to the DOM and when clicked should execute the function bound to it. In this case it should alert "testing". Here is the code.
controller
app.controller('MainCtrl', function($scope, $sce) {
$scope.trustedHtml = $sce.trustAsHtml('<button ng-click="testAlert()">Submit</button>');
$scope.testAlert = function () {
alert('testing')
};
});
HTML
<body ng-controller="MainCtrl">
<div ng-bind-html="trustedHtml"></div>
</body>
$sce.trustAsHtml and ng-bind-html are not meant to build HTML with directives. This technique will not work.
This is because angular works by first compiling and then linking. See the conceptual overview for a good explaination.
In short, by the time you link the HTML defined in your trustAsHtml, it is too late for angular to compile (and therefore understand) the ng-click directive.
In order to dynamically add HTML, you should be looking at the $compile service (and/or directives). Docs are here.
For Angular 1.6.1, I found a solution that worked for me.
template:
<div ng-bind-html="trustAsHtml(content);" init-bind> </div>
In controller:
$scope.trustAsHtml = function(string) {
return $sce.trustAsHtml(string);
};
Directive:
.directive('initBind', function($compile) {
return {
restrict: 'A',
link : function (scope, element, attr) {
attr.$observe('ngBindHtml',function(){
if(attr.ngBindHtml){
$compile(element[0].children)(scope);
}
})
}
};
})

Angular 2 way binding doesn't work with template even though I'm not using primatives

I can't figure out what's wrong with my code. I'm following the example of this fiddle in order to bind the two inputs. What I'm trying to do is just a little more involved- I'd like to load a certain template based on an attribute passed into the directive. I can't figure out what's wrong over here.
This is my html
<!-- template -->
<script type="text/ng-template" id="X-template.html">
<button ng-click='clickMe()'><b>Check model</b></button>
Directive: <input ng-model="this.test"></input>
</script>
<div ng-controller="MyCtrl">
<my-directive type="X"></my-directive>
No Directive:<input ng-model="this.test"></input>
{{this.test}}
</div>
And my JS:
var app = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.this= {test : "asdf"};
$scope.clickMe = function() {
alert($scope.this.test);
}
}
app.directive('myDirective', function() {
return {
restrict: 'E',
compile: function(element, attrs) {
element.append('<div ng-include="\'' + attrs.type + '-template.html\'"></div>');
}
}
});
The issue is with trying to use this, which is a reserved keyword in JavaScript, as a property name.
Try using a different property name. I changed your example to use foo in the link below.
http://jsfiddle.net/01h3ne4y/

data-binding doesn't work after using "appendChild()" to add new element

when i write like this, angular works:
<html ng-app="mptmanager" class="ng-scope">
<body>
<input ng-model = "test" /><br />
{{test}}
</body>
</html>
<script src="js/angular.min.js"></script>
<script src="angular/angularModules.js"></script>
but when i run JS code like this:
var temp = document.createElement('div');
temp.innerHTML = '<input ng-model = "test2"><br />{{test2}}';
document.body.appendChild(temp);
angular has no effect to the new element, so i can only see "{{test2}}" on my page...
how can i make angular work when i try to add or change some element on my page with JS?
You should never do DOM manipulation outside of directives when using Angular. Just to be complete, I'll show you how to make that work anyway. Just inject the $compile service and compile the new markup with the scope.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $compile) {
$scope.foo = 'Default value';
var elem = document.createElement('div');
elem.innerHTML = '<input ng-model="foo">{{foo}}';
document.body.appendChild(elem);
$compile(elem)($scope);
});
Here are proper approaches using directives:
<div my-directive></div>
<div my-directive2></div>
JavaScript:
app.directive('myDirective', function() {
return {
template: '<input ng-model="foo">{{foo}}'
};
});
app.directive('myDirective2', function() {
return {
compile: function(element) {
element.html('<input ng-model="foo">{{foo}}');
}
};
});
In your directive, if you use the link function, which has access to scope, you will have to manually $compile the markup as I demonstrated above, but be careful to avoid an infinite loop. You will usually do this: $compile(element.contents())(scope); If you $compile the element itself, you would create an infinite loop.
Live demos (click).
As dskh briefly mentioned, directives are used to do that kind of stuff in Angular.
The issue here is that Angular doesn't know about the new element, as the routine which adds it lives outside of the Angular scope. You could call $scope.$apply() manually, but i won't consider this best practice.

Resources