Can't require directive in modlule - angularjs

This code generates an error on page open
Unknown provider: $cardProvider <- $card <- cardNumberDirective
Where is a mistake? I see that all should works, but it is not so.
angular.module('card', [])
.controller('CardCtrl', ['$scope', function ($scope) {}])
.directive('card', ['$compile', function ($compile) {
return {
restrict: 'A',
scope: {
cardContainer: '#',
width: '#',
placeholders: '=',
options: '=',
messages: '=',
},
controller: 'CardCtrl',
link: function (scope, element, attributes, cardCtrl) {
// Some logic is here...
new Card(opts);
}
};
}])
.directive('cardNumber', ['$compile', function ($compile) {
return {
restrict: 'A',
scope: {
ngModel: '='
},
require: [
'^card', // this directive can't be find
'ngModel'
],
link: function (scope, element, attributes, ctrls) {
}
};
}])
Thank you for any suggestions.

Related

how to use $sce in Angular directive

Basically we would like to sanitize html data as soon I used $sce it does not work is there any alternate option to use instead $sce ?
app.directive('stack', ['$timeout', function($timeout) {
return {
restrict: 'A',
controller: 'StackController',
scope: {
onReady: '&?',
onChange: '&',
onDragStart: '&',
onDragStop: '&',
onResizeStart: '&',
onResizeStop: '&',
options: '='
},
link: function(scope, element, attrs, controller, $sce) {
var stack = controller.init(element, scope.options);
var serializeItems = function() {
const data = [];
$(element).children().each((index, item) => {
const $item = $($sce.trustAsHtml(item)).data('_stack');
data.push({
id: $item.id,
type: $($sce.trustAsHtml(item)).attr('type'),
position: [
$item.x,
$item.y,
],
size: [
$item.width,
$item.height,
],
});
});
return data;
}
}
};
}]);
Thank in advance please guide
Your injecting $sce in the wrong way:
app.directive('stack', ['$sce', function($sce){
return {
restrict: 'C',
link: function (scope, element, attrs) {
...$sce(your content) ...
}
}
}]);
Notice that the module should be injected to the directive, as opposed to being injected to the link function.
I would use $sce with a wrapping function, just to render stuff in the View/HTML, so, in
the controller:
scope.trustAsHtml(str) {
return $sce.trustAsHtml(str);
}
in the view/html:
<div>{{trustAsHtml(yourData)</div>

Passing arguments to nested directives in Angular

I am trying to pass arguments from a parent directive to a child directive but the arguments seem to be undefined. Is there a right way to do this?
}).directive('flipper', function ($timeout) {
return {
template: '<div class="flipper" ng-class="{big: big}"><div class="inner animated " ng-style="rotatorTop()"><ul><li ng-repeat="app in apps">{{app.name}}</li></ul></div></div>',
restrict: 'E',
replace: false,
scope: {
apps: "=",
big: "=",
sizes: "="
},
link: function ($scope, $element, $attrs) {
// undefined!
alert($scope.apps);
...
}
};
}).directive('slogan', function ($window) {
return {
template: '<div class="message"><div class="message-big"><div class="black">{{lines[0]}}<flipper apps="apps" class="big" sizes="flipperSize"></flipper>' +
'</div><div class="black">{{lines[1]}}</div><div class="black">{{lines[2]}}</div></div></div>',
restrict: 'E',
replace: false,
transclude: true,
scope: {
apps: "=",
lines: "="
},
link: function ($scope, $element, $attrs) {
...
}
};
});
Yes there is. As your code is quite incomplete, I've made this simple directive to demonstrate how you can pass values from the controller to a parent directive and a child directive.
myApp.directive('cdParent', function() {
return {
restrict: "AE",
template: "<div cd-child option=\"option\" text=\"text\">",
scope: {
option: "="
},
link: function(scope, elem, attrs) {
console.log("inside parent directive: " + scope.option); // will log the color for the controller
scope.text = "Hello nested directives";
}
}
});
myApp.directive('cdChild', function() {
return {
restrict: "AE",
template: "<pre style=\"color: {{option}}\">{{text}} ({{option}})</pre>",
scope: {
option: "=",
text: "="
},
link: function(scope, elem, attrs) {
console.log("inside child directive: " + scope.option);
}
}
});
also, the link function doesn't do dependency injection as a controller does, so it's arguments should be scope, element, attrs not $scope, $element, $attrs, argument order makes a difference here

Inner directive is executed first - should be second

I've got custom directive that has other custom directive in it.
Problem is that first is executed link func from inner directive not outer one. Why?
In outer directive I've got calulation that are crucial for inner directive.
Priority didn't help.
Here is code sample:
App.directive('ifSearchSelect', ['$system',function ($system) {
return {
restrict: "E",
replace: true,
scope: {
ngModel: "=",
kolumna: "="
},
require:"ngModel",
priority:100,
link: function (scope, element, attrs, ctrl) {
console.log('Not first but I expected it to be');
//more funcs
},
templateUrl: "template/if-form-pola/select.html"
};
}])
.run(["$templateCache", function ($templateCache) {
$templateCache.put("template/if-form-pola/select.html",
"<div>" +
"<if-input-select ng-model=\"model.ngModel.wartosc\" kolumna=\"::model.kolumna\" dane=\"::model.wartosci\"></if-input-select>" +
"</div>"
);
}])
.directive('ifInputSelect', ['$system',function ($system) {
return {
restrict: "E",
replace: true,
scope: {
ngModel: "=",
kolumna: "="
},
require:"ngModel",
priority:50,
link: function (scope, element, attrs, ctrl) {
console.log('First supposed to be second');
//more funcs
},
templateUrl: "template/if-input-pola/select.html"
};
}])
.run(["$templateCache", function ($templateCache) {
$templateCache.put("template/if-input-pola/select.html",
"<div>" +
"Input directive" +
"</div>"
);
}])
Template:<if-search-select ng-model="data" kolumna="kolumna"></if-search-select>
I found solution pre in link function - here's source http://www.undefinednull.com/2014/07/07/practical-guide-to-prelink-postlink-and-controller-methods-of-angular-directives/
Changed first directive
App.directive('ifSearchSelect', ['$system',function ($system) {
return {
restrict: "E",
replace: true,
scope: {
ngModel: "=",
kolumna: "="
},
require:"ngModel",
link: {
pre: function (scope, element, attrs, ctrl) {
console.log("Now it's first");
//more funcs
},
}
templateUrl: "template/if-form-pola/select.html"
};
}])

Can an angularjs Directive require Itself?

Can a directive require itself? Here's an example:
app.directive('menu', function () {
return {
restrict: 'E',
require: '?^menu',
link: function(scope, element, attrs, ctrl) {
console.log('ctrl: ', ctrl);
if (ctrl) {
element.addClass('nested');
} else {
element.addClass('notnested');
}
}
};
});
In my test it doesn't seem to work (ctrl is always undefined). See the plunk
BTW, after this question was answered I discovered that in this case the caret (^) has no effect and the controller passed to the link function is always the instance's own controller. [ plunk ]
You should directly define controller function to expose directive API to other directives:
app.directive('menu', function () {
return {
restrict: 'E',
require: '?^menu',
controller: function($scope){ },
link: function(scope, element, attrs, ctrl) {
console.log('ctrl: ', ctrl);
if (ctrl) {
element.addClass('nested');
} else {
element.addClass('notnested');
}
}
};
});
See http://plnkr.co/edit/cKFuS1lET56VOOYD5rrd?p=preview
With angular 1.4x, you actually can now limit the require statement to parent elements only and exclude the element itself. If you change
require: '?^menu' to require: '?^^menu' (notice the second caret) so that you get
app.directive('menu', function () {
return {
restrict: 'E',
require: '?^^menu',
controller: function($scope){ },
link: function(scope, element, attrs, ctrl) {
console.log('ctrl: ', ctrl);
if (ctrl) {
element.addClass('nested');
} else {
element.addClass('notnested');
}
}
};
});
the code now works as expected.
See http://plnkr.co/edit/2uDUO0LcgDX7xEuBtsJ2?p=preview
I guess here the problem is not with the directive referencing itself. The directive will not know which controller to refer to until specified or defined. To access a controller either it has to be defined or referenced in the directive as below.
app.directive('menu', function () {
return {
restrict: 'E',
controller: 'MainCtrl',
require: ['?^menu'],
link: function(scope, element, attrs, ctrl) {
console.log('ctrl: ', ctrl[0]);
if (ctrl) {
element.addClass('nested');
} else {
element.addClass('notnested');
}
}
};
});

Link function not called

I have a directive defined as following -
.directive('codesection', ['$compile', function ($compile) {
return {
restrict: 'E',
scope: { current: '=', parent: '=', index: '=', params: '=' },
controller: ['Messages', '$scope', 'Modals', 'framewidth', '$http', '$rootScope', function (Messages, $scope, Modals, framewidth, $http, $rootScope) {
//code
}],
link: function (scope, element, attr) {
element.bind('mouseover', function (ev) {
ev.stopPropagation();
var wrappers = angular.element(document.getElementsByClassName('codesection'));
angular.forEach(wrappers, function (value, key) {
angular.element(value).children('span').removeClass('br');
});
element.children('.codesection').children('span').addClass('br');
});
},
compile: function (tElement, tAttr, transclude) {
var contents = tElement.contents().remove();
var compiledContents;
return function (scope, iElement, iAttr) {
if (!compiledContents) {
compiledContents = $compile(contents, transclude);
}
compiledContents(scope, function (clone, scope) {
iElement.append(clone);
});
};
},
templateUrl: './partials/directives/codesection.html',
replace: true
}
}])
The issue I am having is that Link functions is never called. Thank you!
P.S. The reason for the Compile logic is that the directive is recursive.
If you mean that link: function (scope, element, attr) { isn't called then it's pretty clear: The compile function already returns a link function. What is defined as link: doesn't matter anymore and is ignored.

Resources