Angular 1 custom directive not executing - javascript

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}}

Related

Error: [$compile:nonassign] Expression 'undefined' in attribute [ATTRIBUTENAME] used with directive '[DIRECTIVENAME]' is non-assignable?

When I'm trying to transform date inside the directive's body I get error:
Error: [$compile:nonassign] Expression 'undefined' in attribute
[ATTRIBUTENAME] used with directive '[DIRECTIVENAME]' is
non-assignable!
I am using angular version 1.4.14
Expected result: in my template directive will return class name -
div class="news-block-container sm-padding-right"
What can cause this problem? Thanks for your answer
here is an example of my code:
'use strict';
angular.module('test.directives')
.directive('test', function () {
var templatePath = "/views/templates/testTemplate.tmpl.html";
return {
restrict: 'E',
scope: {
position: '=',
},
templateUrl: templatePath,
link: function (scope, element, attrs) {
scope.$watch('position', function () {
if (scope.position === "left") {
scope.position = "sm-padding-right";
}
else {
scope.position = "sm-padding-left";
}
});
}
}
});
view - directive usage
<test-template position="'left'"></test-template>
//!TEMPLATE! - testTemplate
<div>
<a href="{{#}}">
<div class="news-block-container {{position}}">
</div>
</a>
</div>
Just use ng-class directive to assign class dynamically
<div>
<a href="{{#}}">
<div class="news-block-container" ng-class="position">
</div>
</a>
</div>
change angular.module('test.directives')
to this angular.module('test.directives',[])
Also remove the curly brackets around hash in template
change <a href="{{#}}">
to this <a href="#">

Directive with same template but with dynamic content

HTML :
<div custDirective id="managerNames"></div>
<div custDirective id="empNames"></div>
Template.html
<div ng-repeat="name in names">
<ol><li>{{name}}</li></ol>
</div>
Directive link function :
if(attr.id === "name"){
scope.names = ["A","B","C","D"];
}else{
scope.names = ["E","F","G","H"];
}
I want to get the dynamic list based on the id attribute.i.e, If id is managerNames then my ng-repeat should repeat a,b,c,d else it should repeat e,f,g,h.
How to achieve this? I am using angular.js 1.2 version.
you can send an attribute to your link where it will check on the value you send to it and work accordingly to it
Here is an example :
//Directive
angular.module('yourModule').directive('directiveName',
function($parse) {
return {
restrict: 'E',
templateUrl: "your/template.html",
scope: {
check: '#',
},
link: function(scope, element, attrs) {
if(scope.check == "whatever"){
}
}
})
//HTML
<directive-name check="whatever"></directive-name>

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>

Passing a function to an Angular validation directive

I have the following code, note the name-valid and validation-function tags on the input field.
<form name="createForm" novalidate>
<div style="display: flex; width: 300px">
<div style="flex: 3;">
Name
</div>
<div style="flex: 5;">
<input type="text" name="listName" ng-model="newListName"
ng-minlength="3" name-valid validation-function="someFunction"/>
</div>
</div>
<div ng-show="createForm.listName.$error.unique &&
!renameGoldenForm.listName.$error.minlength">already exists</div>
<div ng-show="createForm.listName.$error.minlength">too short</div>
<div style="margin-top: 10px">
<button ng-click="createList()" ng-disabled="createForm.listName.$invalid">
Create</button>
</div>
</form>
And here is the JS:
window.angular.module("myModule").directive("nameValid", [
"$log",
function($log) {
return {
require: "ngModel",
scope: {
validationFunction: "="
},
link: function(scope, ele, attrs, c) {
scope.$watch(attrs.ngModel, function() {
var v = scope[attrs.ngModel];
if (!v || !((v).trim()) || v.length < 4) {
c.$setValidity("unique", true);
c.$setValidity("minlength", false);
return;
}
scope.validationFunction(v, scope.selectedListId)
.success(function(data) {
c.$setValidity("unique", data.unique);
c.$setValidity("minlength", data.minlength);
});
});
}
};
}
]);
The problem is that having require and scope seems to break.
Is there a way to pass a custom validate function to my directive? I'm not sure how to go about it.
I've tried removing require: 'ngModel' and adding ngModel in scope, but that did not work either.
If I remove scope and hard code the function in the watch block, that works, but obviously, that defeats the purpose of having a pointer to a specific function.
To bind a controller function to your directive, you have to use the & bindings (expression binding) which allows the directive to call an expression or a function defined by a DOM attribute.
For example :
Controller
(function(){
function Controller($scope, $q) {
//Declare the func which will be bind to the directive
$scope.func = function (data1, data2) {
return new $q(function(resolve){
resolve(data1 === data2);
});
}
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
Then we will bind this function into your directive, and we can call it into the link function.
Directive
(function(){
function directive() {
return{
restrict: 'AE',
scope: {
function: '&'
},
link:function(scope, element, attrs) {
//Then, pass an object as argument to your function
var promise = scope.function({data1: 5, data2: 5});
//Retrieve result
promise.then(function(data){
console.log(data);
});
}
};
}
angular
.module('app')
.directive('directive', directive);
})();
To finish, you can call your directive with a function attribute, in order to bind the function to your directive.
HTML
<body ng-app="app" ng-controller="ctrl">
<directive function="func(data1, data2)"></directive>
</body>

AngularJS - compiled html in tootilp

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?

Categories

Resources