AngularJS - compiled html in tootilp - javascript

I am trying to use tooltip in ng-repeat based on AngularJs: grab compiled html and set into tooltip
However I a somehow not able to make it work.
My html-
<tr ng-repeat="row in docDetails">
<td class="useBootstrap uploadedDocs">
<div class="useBootstrap col-sm-2" upload-info="row" index="{{$index}}">
<p tooltip-html-unsafe="{{tooltips[$index] }}"> {{ row.FileName | limitTo: 15 }}{{row.FileName.length > 15 ? '...' : ''}}</p>
My directive
app.directive('uploadInfo', function ($compile, $timeout) {
/* wrap in root element so we can get final innerHTML*/
var tipTemplate = '<div> {{row.FileName}} injected in the tooltip </p><div>';
return {
link: function (scope, el, attrs) {
var tipComp = $compile(tipTemplate)(scope)
$timeout(function () {
scope.tooltips[attrs.index] = tipComp.html()
});
}
}
});
Controller i have declared
$scope.tooltips = [];
Can you tell me if I am missing anything?

Related

Angular 1 custom directive not executing

I have my directive defined as follows:
'use strict;'
angular.module('clientApp')
.directive('afterLast', ['$ocLazyLoad','$timeout',function($ocLazyLoad, $timeout){
console.log('entered directive');
return {
restrict: 'A',
link: function(scope, elem, attr){
if (scope.$last === true){
console.log('entered directive')
$timeout(function(){
$ocLazyLoad.load(['some files'])
})
}
}
}
}]);
And, I am using it as an attribute as follows:
<div ng-repeat="topicObject in module.topics track by $index" afterLast>
<div class="ft-section">
<div ng-repeat="learningPointObject in topicObject.learningPoints track by $index">
<div class="ft-page">
<h2 class="module-name" style="text-align: center;">{{module.name | capitalize:true}}</h2>
<h3 class="topic-name">{{topicObject.name | capitalize:true}}</h3>
<h4>{{learningPointObject.name | capitalize}}</h4>
<hr>
</div>
</div>
</div>
</div>
But my directive is not executing. Even the console.log statements inside and outside the link function are not working.
1. Am I using directives the correct way?
2. If yes, what could be the reasons for it not working?
In the HTML the directive name needs to be in kebab-case, not camelCase.
<!-- ERRONEOUS camelCase
<div ng-repeat="topicObject in module.topics track by $index" afterLast>
-->
<!-- USE kebab-case -->
<div ng-repeat="topicObject in module.topics track by $index" after-last>
For more information, see AngularJS Developer Guide - Directive Normalization
directive : for last watch of ng-repeat..
app.directive('afterLast',function(){
return {
restrict: 'A',
scope: {},
link: function (scope, element, attrs) {
if (attrs.ngRepeat) {
if (scope.$parent.$last) {
if (attrs.afterLast !== '') {
if (typeof scope.$parent.$parent[attrs.afterLast] === 'function') {
// Executes defined function
scope.$parent.$parentattrs.afterLast;
} else {
// For watcher, if you prefer
scope.$parent.$parent[attrs.afterLast] = true;
}
}
}
} else {
throw 'ngRepeatEndWatch: ngRepeat Directive required to use this Directive';
}
}
}
});
function call on last call
$scope.layoutDone = function () {
you want your desire data here
}
html
{{module.name | capitalize:true}}
{{topicObject.name | capitalize:true}}
{{learningPointObject.name | capitalize}}

Angular directives in $http response

Angular 1.5
My $http data service returns html encoded text with directives too, like ng-click in the text.
I need to display the html and have the ng-click directives get activated.
To display I am doing this and it works, but ng-clicks don't work:
<div class="mt10" ng-repeat="row in aqdas.Paragraphs" ng-cloak>
<span ng-bind-html="TrustDangerousSnippet(row.Text)" >
{{row.Text}}
</span>
</div>
Here is TrustDangerousSnippet:
$scope.TrustDangerousSnippet = function (text) {
var val = $sce.trustAsHtml(text);
return val;
};
How can I edit TrustDangerousSnippet so that the ng-click's in the text are turned on once $http downloads the code?
Use this Directive also with your code. to bind html element in directive use complie. it will work..
.directive('compile', ['$compile', function ($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
return scope.$eval(attrs.compile);
},
function(value) {
element.html(value);
$compile(element.contents())(scope);
}
);
};
}])
I added the Directive Suresh included and changed the HTML to look like this, it works now. (add 'compile' to the binding element)
<div class="mt10" ng-repeat="row in aqdas.Paragraphs" ng-cloak>
<span compile ng-bind-html="TrustDangerousSnippet(row.Text)" >
{{row.Text}}
</span>
</div>

Dynamic ng-click does not call function

I wish to make a dynamic table in AngularJS, but the problem is ng-click does not call the function.
Here is the fiddle : fiddle
Here is the code :
General template :
<div class="box">
<dynamic-table></dynamic-table>
</div>
Directive template :
<table class="table table-striped">
<thead>
<tr>
<th ng-repeat="column in columns" ng-bind="column.label"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="content in data">
<td ng-repeat="column in columns">
<!-- Problem is here (column[function] displays 'displayCategory') -->
<a href ng-click="column[function]()">{{ content[column.field] }}</a>
</td>
</tr>
</tbody>
</table>
Directive code :
app.directive('dynamicTable', function () {
return {
restrict: 'E',
templateUrl:'/template/Directive/dynamic-table.html',
scope: true,
link: ['$scope', function($scope) {
$scope.updateCategory = function() {
console.log("WOW");
};
}]
};
});
When I display : column[function], it shows updateCategory. I don't understand why when I click on it, the function is not launched...
Have you got an idea ?
That's because column[function] returns a string, not a reference to the function itself. You should call the function directly, like:
<td ng-repeat="column in columns">
<!-- Problem is here (column[function] displays 'displayCategory') -->
<a href ng-click="updateCategory (column)">{{ column.field }}</a>
</td>
and inside the directive to have something like:
controller: ['$scope', function($scope) {
$scope.updateCategory = function(columnData) {
console.log(columnData.field);
};
}]
Check demo: JSFiddle.
First of all, you link function declaration is not correct:
link: ['$scope', function($scope) {
$scope.updateCategory = function() {
console.log("WOW");
};
}]
It is the format of controller function. Change it to:
link: function($scope) { ... }
Angular will do the injection for you.
Secondly, specify a dispatcher function on the scope. Inside the dispatcher, determine which function to call:
$scope.dispatcher = function (column) {
var fn = column.function;
fn && angular.isFunction($scope[fn]) && $scope[fn]();
};
And specify ng-click="dispatcher(column)" in the HTML.
Please see this fiddle as maybe it will suit your needs.
http://jsfiddle.net/tep78g6w/45/
link:function(scope, element, attrs) {
scope.updateCategory = function() {
console.log("WOW");
};
scope.doSomething = function(func) {
var test = scope.$eval(func);
if(test)
test();
}
}
}
Also, link function has parameters that are sent to it, this is not a place to use DI. Please see in the fiddle the correct approach. As far as the dynamically calling the function, I went with different approach and it works. The approach you took is not going to work because you need a way for the string to be a function, it needs to have a reference to a function.

Custom directive: How evaluate bindings with dynamic HTML

Setup:
Very simplified HTML:
<td ng-repeat="col in cols">
<div ng-bind-html="col.safeHTML"></div>
</td>
JS controller:
$scope.cols = [
{
field : 'logo',
displayName : 'Logo',
cellTemplate: '<div style="color:red">{{col}}</div>'
},
{
field : 'color',
displayName : 'Color',
cellTemplate: '<div style="color:green">{{col}}</div>
}
];
JS link directive link function:
for (var i = 0, j = $scope.cols.length;
i < j;
i++) {
if ($scope.cols[i].hasOwnProperty('cellTemplate')) {
$scope.cols[i].safeHTML = $sce.trustAsHtml($scope.cols[i].cellTemplate);
}
}
And it is escaping correctly the HTML but the bindings ({{some_var}}) are not being interpolated.
How can make Angular compute the bindings in the safe HTML? I tried to use several variations of bind like ngBindTemplate but was for no use :(
You actually want to use the $compile service if you plan to dynamically compile angular components and add them to the DOM manually.
With a little bit of custom directive work, you can make this work pretty easily.
function compileDirective($compile) {
return {
restrict: 'A',
link: function(scope, elem, attrs) {
//Watch for changes to expression
scope.$watch(attrs.compile, function(newVal) {
//Compile creates a linking function
// that can be used with any scope
var link = $compile(newVal);
//Executing the linking function
// creates a new element
var newElem = link(scope);
//Which we can then append to our DOM element
elem.append(newElem);
});
}
};
}
function colsController() {
this.cols = [{
name: "I'm using an H1",
template: "<h1>{{col.name}}</h1>"
}, {
name: "I'm using an RED SPAN",
template: "<span style=\"color:red\">{{col.name}}</span>"
}];
}
angular.module('sample', [])
.directive('compile', compileDirective)
.controller('colsCtrl', colsController);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.4/angular.min.js"></script>
<div ng-app="sample">
<ul ng-controller="colsCtrl as ctrl">
<li ng-repeat="col in ctrl.cols">
<!-- The "compile" attribute is our custom directive -->
<div compile="col.template"></div>
</li>
</ul>
</div>

Generate HTML string from AngularJS template string

I have angularjs template as a string including "ng-repeat" and other directives. I want to compile it in the controller to produce the result HTML as string.
Example on what I want to apply in Angular:
Input:
-------
var template = '<div ng-repeat="item in items">{{item.data}}</div>';
Output:
--------
var result = '<div>1</div><div>2</div><div>3</div><div>4</div>';
I want this to be done in the controller I've and I tried the following:
var template = '<div ng-repeat="item in items">{{item.data}}</div>';
var linkFunction = $compile(template);
var result = linkFunction($scope);
console.log(result); // prints the template itself!
Thanks!
Give this a whirl:
var template = angular.element('<div ng-repeat="item in items">{{item.data}}</div>');
var linkFunction = $compile(template);
var result = linkFunction($scope);
$scope.$apply();
console.log(template.html());
For this purpose I made myself a directive couple of projects ago:
angular.module('myApp')
.directive('ngHtmlCompile', ["$compile", function ($compile) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch(attrs.ngHtmlCompile, function (newValue, oldValue) {
element.html(newValue);
$compile(element.contents())(scope);
});
}
}
}]);
and then for example:
<div ng-html-compile='<div ng-repeat="item in items">{{item.data}}</div>'></div>
or even the string can be dynamic:
<div ng-repeat="item in items" ng-html-compile="item.template">
</div>

Categories

Resources