$sce.trustAsHtml not working - angularjs

Alright, so the following below that I've tested in code works:
javascript:
var string = '<p>hello</p>';
$scope.html = $sce.trustAsHtml(string);
html:
<span ng-bind-html="html"></span>
The thing I'm really trying to do is this: Pulling a bunch of items from the server in JSON form. One of the JSON's key is called "description", which is just a long string of html code.
I'm pushing these items into a $scope array so I can show them on the page through an ng-repeat directive. The code below summarizes how it's being done:
javascript:
$.getJSON('someURL', function(data) {
$scope.items = [];
for (var i = 0; i < data.count; i++) {
var item = {};
item.description = $sce.trustAsHtml(data.item[i].description);
$scope.items.push(item);
}
});
html:
<p ng-repeat="item in items">
<span ng-bind-html="item.description"></div>
</p>
This isn't producing any output for some reason. Something I read was that whatever variable you bind the $sce.trustAsHtml() to must be a $scope variable. In this case, I'm setting it to a regular variable "item.description" and then adding it to a $scope.item array.
I suspect this may be why it's not working, but I don't know how to go about fixing it.
Can anyone help with this?
Thanks!

Try <span ng-bind-html="'{{item.description}}'"></span>.
Something like this worked for me.

With AngularJS 1.4.9 it worked for me like this:
Controller:
.controller('MyCtrl', ['$scope', '$sce',
function($scope, $sce) {
$scope.infoText = $sce.trustAsHtml('My <strong>HTML text</strong>');
}
])
Template:
<span ng-bind-html="infoText"></span>

Related

ng-repeat is not refreshed when ng-click method called from directive

I am working on creating reusable directive which will be showing composite hierarchical data .
On first page load, Categories like "Server" / "Software"/ "Motherboard" (items array bound to ng-repeat) would be displayed . If user clicks on "Server" then it would show available servers like "Ser1"/"Ser2"/"Ser3".
html :
<div ng-app="myApp" ng-controller="myCtrl" ng-init="init()">
<ul>
<li ng-repeat="item in items">
<div my-dir paramitem="item"></div>
</li>
</ul>
</div>
Now first time Items are loading, but clicking on any item is not refreshing ng-repeat. I have checked ng-click, "subItemClick" in below controller, method and it is being fired. However the items collection is not getting refreshed.
http://plnkr.co/edit/rZk9cbEJU90oupVgcSQt
Controller:
var myApp = angular.module('myApp', []);
myApp.controller('myCtrl', ['$scope', function($scope) {
$scope.init = function() {
$scope.items = [{iname: 'server',subItems: ['ser1', 'ser2','ser3']}
];
};
$scope.subItemClick = function(sb) {
if (sb.subItems.length > 0) {
var zdupitems = [];
for (var i = 0; i < sb.subItems.length; i++) {
zdupitems.push({
iname: sb.subItems[i],
subItems: []
});
}
$scope.items = zdupitems;
}
};
}])
.directive('myDir', function() {
return {
controller: 'myCtrl',
template: "<div><a href=# ng-click='subItemClick(paramitem)'>{{paramitem.iname}}</a></div>",
scope: {
paramitem: '='
}
}
});
I am expecting items like ser1/ser2 to be bound to ng-repeat on clicking "Server" but it is not happening .
Any help?
I think that onClick is screwing up the method's definition of $scope. In that context, the $scope that renders the ngRepeat is actually $scope.$parent (do not use $scope.$parent), and you're creating a new items array on the wrong $scope.
I realize the jsfiddle is probably a dumbed down example of what you're dealing with, but it's the wrong approach either way. If you need to use a global value, you should be getting it from an injected Service so that if one component resets a value that new value is reflected everywhere. Or you could just not put that onClick element in a separate Directive. What's the value in that?

AngularJS Communication between ng-repeat and controller

I've just started using AngularJS, and as a project I decided to build a simple app for managing bookmarks. I want to be able to maintain a list of bookmarks and add/remove items. I'm using Django with Django REST framework, and Angular.
So far I've written a service to grab the bookmarks from the database, and I can print them to the console from my controller, but ng-repeat doesn't seem to be seeing them.
Here's my code for the service:
.factory('BookmarkService', ["$http", function ($http) {
var api_url = "/api/bookmarks/";
return {
list: function () {
return $http.get(api_url).then(function (response) {
return response.data
})
}
}
}]);
And for the controller:
.controller("ListController",
["$scope", "BookmarkService", function ($scope, BookmarkService) {
$scope.bookmarks = BookmarkService.list();
console.log($scope.bookmarks);
}]);
And here's the HTML:
<div ng-controller="ListController as listCtrl">
<md-card>
<md-card-content>
<h2>Bookmarks</h2>
<md-list>
<md-list-item ng-repeat="bookmark in listCtrl.bookmarks">
<md-item-content>
<div class="md-tile-content">
<p>{[{ bookmark.name }]} - {[{ bookmark.url }]}</p> // used interpolateProvider to allow "{[{" instead of "{{"
</div>
<md-divider ng-if="!$last"></md-divider>
</md-item-content>
</md-list-item>
</md-list>
</md-card-content>
</md-card>
</div>
When I print to the console from the controller I can see a promise object but ng-repeat isn't repeating:
image of promise object
I'd really appreciate if someone could help me to find my mistake and to understand why it is happening. I'm still not entirely comfortable with how all these parts fit together.
Thanks for your time!
There's two problems that I see with the code in question.
The first is that using the controller as syntax (ng-controller="ListController as listCtrl") requires properties to be bound to the controller instance and not to the scope if you address them using the controller name. In your case,
.controller("ListController",
["BookmarkService", function (BookmarkService) {
this.bookmarks = BookmarkService.list();
console.log(this.bookmarks);
}]);
The second is that you are assigning a promise to your $scope.bookmarks property. The repeater is expecting an array of objects to iterate over. You really want to assign the value resolved by the promise to $scope.bookmarks.
Instead of this
$scope.bookmarks = BookmarkService.list();
Do this
BookmarkService.list().then(function(result){
this.bookmarks = result;
});
The final version of your controller should look something like this
.controller("ListController",
["BookmarkService", function (BookmarkService) {
this.bookmarks = BookmarkService.list();
console.log(this.bookmarks);
}]);
This is simple. Ng-repeat is not working with promises. So, you can go with two ways:
BookmarkService.list().then(function(responce){
$scope.bookmarks = responce.data;
});
Another way is to create own repiter ^)
Ng-repeat doc

AngularJS Passing scope to directive via a custom filter function $rootScope:infdig

I've created simple custom directive in angularJs. In that directive I am passing an array of objects as tableLayout. Please see my working jsfiddle with no errors.
JS Fiddle Working
However I need to pass a filtered tableLayout. I've created a function in the scope called filterFilterFn to filter the values and then pass it into the scope of my directive. When i do this I get a $rootScope:infdig error.
Js Fiddle w/ filterFunction NOT working
Reading another similar problem it was to do with the using the default filter in angularJs. Hence why I've have done a custom filter function in the scope. But I am still getting a same error. Advice on what I am doing wrong would be appreciated.
Non-working code below:
<div ng-app="myApp" ng-controller="mainCtrl">
<script type="text/ng-template" id="/template">
<button ng-click="testFn()">Test</button>
<div layout="row">
<div flex ng-repeat="col in [1,2,3]"><span>HEADER{{$index}}</span>
<div layout="column">
<div flex style="border: 1px solid black;" ng-repeat="row in [1,2,3]">{{$index}}</div>
</div>
</div>
</div>
</script>
<button ng-click="testFn()">Test 2</button>
<form-table table-layout=formFilterFn('table_id',1)></form-table>
</div>
var app = angular.module('myApp', ['ngMaterial']);
app.controller('mainCtrl', function($scope) {
$scope.tableLayout =[{"head_id":"GAP Assessment","table_id":"1","table_name":"GAP Table","element_id":"0","element_name":"Action Reference","sort_order":"0","is_multirow":"1","flex":"30","element_sort_order":"4","is_show":"0"},{"head_id":"GAP Assessment","table_id":"1","table_name":"GAP Table","element_id":"1","element_name":"Audit Criteria","sort_order":"0","is_multirow":"1","flex":"30","element_sort_order":"0","is_show":"1"},{"head_id":"GAP Assessment","table_id":"1","table_name":"GAP Table","element_id":"3","element_name":"Document Reference","sort_order":"0","is_multirow":"1","flex":"10","element_sort_order":"3","is_show":"1"},{"head_id":"GAP Assessment","table_id":"1","table_name":"GAP Table","element_id":"4","element_name":"Findings - General","sort_order":"0","is_multirow":"1","flex":"20","element_sort_order":"1","is_show":"1"},{"head_id":"GAP Assessment","table_id":"1","table_name":"GAP Table","element_id":"5","element_name":"Findings Details","sort_order":"0","is_multirow":"1","flex":"40","element_sort_order":"2","is_show":"1"}]
$scope.testFn=function(){
console.log("Test");
}
$scope.formFilterFn = function(key,value){
var output = [];
var input = $scope.tableLayout;
for (var x =0; x < Object.keys(input).length; x++){
if (input[x][key]==value){
output.push(input[x]);
}
}
return output;
}
});
app.directive('formTable', function() {
return {
scope:{tableLayout:'='},
link: function(scope,element,attrs){ // normal variables rather than actual $scope, that is the scope data is passed into scope
scope.column=[1,2,3];
scope.testFn=function(){
console.log(scope.tableLayout);
}
//function and scopes go here
},//return
transclude:true,
templateUrl: '/template',
restrict: 'E'
}
})
2 way bindings is causing the loop here, you can bind your scope with '&'.
Please check: http://jsfiddle.net/pa13f6gb/1/
scope:{ tableLayout:'&' },
From https://docs.angularjs.org/guide/directive:
"Because of this, '&' bindings are ideal for binding callback functions to directive behaviors."
I wouldn't personally call it a filter, just to avoid confusion with actual angular filters. Yes it's a filtering function.
The infinite digest is happening because the filter function is returning a new array every time. If you set a variable to the result of the filter, and bind the table to that, it should work.

AngularJS : update bindings ng-bind-html

I've go a problem with binding. I use the "ng-bind-html" directive, because the details text of the object to display contains HTML code. Unfortunatly the text doesn't update when the object changes. 'title' and 'kurztext' change its values but 'langtext' (the html bound) not. Here's the code I use:
<div class="content scrollContainer" ng-model="selectedItem">
<h2 class="header">{{selectedItem.titel}}</h2>
<div class="kurztext" ng-show="selectedItem.kurztext">{{selectedItem.kurztext}}</div>
<div class="langtext" ng-bind-html="selectedItem.langtext"></div>
</div>
In Javascript I just pick an object out of an array and assign it to $scope.selectedItem to change the displayed item. Here's my JS code (should not be relevant to the problem):
var items;
var app = angular.module("app", ["ngSanitize"]);
app.controller("MainCtrl", function ($scope, $sce){
$scope.items = items;
$scope.selectedItem = $scope.items[0];
$scope.showItem = function(item){ // called on click on list item
$scope.selectedItem = item;
}
$scope.openItemLink = function(id){
for (var i=0; i<$scope.items.length; i++){
if ($scope.items[i].uid==id){
$scope.showItem($scope.items[i]);
break;
}
}
}
$scope.getLink = function(id){
var it = 0;
for (var i=0; i<$scope.items.length; i++){
if ($scope.items[i].uid==id){
it = $scope.items[i];
return it.titel;
}
}
return "----";
}
});
Any ideas?
you need to sanitize it, add angular-sanitize.js and in your module
var App = angular.module('process', ['ngSanitize']);
in your controller
App.controller(
'Init',
[
'$scope', '$sce',
function($scope, $sce)
and your code
$scope.details = $sce.parseAsHtml($scope.details);
i know that if i don't do that it doesnt work too,
according to the documentation
By default, the innerHTML-ed content will be sanitized using the $sanitize service.
To utilize this functionality, ensure that $sanitize is available,
for example, by including ngSanitize in your module's dependencies (not in core Angular.)
You may also bypass sanitization for values you know are safe.
To do so, bind to an explicitly trusted value via $sce.trustAsHtml.
See the example under Strict Contextual Escaping (SCE).

angular scope variable has no data

I'm pretty new to angular js but it seems like my simple code should work. Here is the html:
<body ng-app="MyHomepage">
<div ng-controller="RedditLoad">
{{a}}
<ul>
<li ng-repeat="article in a">
{{article.data.title}}
</li....
and here is my angualr_app.js:
var App = angular.module('MyHomepage', [])
function RedditLoad($scope){
$.getJSON("http://www.reddit.com/.json?jsonp=?", function(data) {
var data_array = [];
$.each(data.data.children, function(i,item){
data_array.push(item);
});
console.log(data_array);
$scope.a = data_array;
});
}
What am I doing wrong? console.log(data_array); is showing the correct values but the data wont seem to get passed to the template.
The getJSON callback isn't executed in the angular context so angular doesn't know about your changes and won't refresh the bindings. When code is called from an external source (like a jQuery event ), you have to encapsulate your scope changes in an $apply call:
$scope.$apply(function{
$scope.a = data_array;
}

Resources