Dynamically Create directive - angularjs

i've created a directive dynamically and then i passed a data to this directive but this directive not rendered and i can access passed data into link function, and here my snippet code:
var table = $compile("<user-priv data=object ><user-priv>")($scope);
angular.element(document).find('#privModal').find('.modal-body').append(table);
angular.element(document).find('#privModal').modal('show')
And here is Directive code
.directive('userPriv', [function() {
return {
restrict: 'A',
scope: {
data: '=?'
},
templateUrl: 'file/angular/templates/privList.html',
link: function(scope, iElement, iAttrs) {
console.warn(scope.data);
},
controller: function($scope) {
console.log('test');
}
};
}])

Not sure what you succeeded or not from your post, but one thing looks off:
restrict: 'A' should be restrict: 'E' since you're using the directive as an Element, not as an Attribute.

Parameter passed to directive are always shown as html attribute: in your code you are missing some colons "".
Change your $compile line to:
var table = $compile("<user-priv data="object" ><user-priv>")($scope);

Related

Calling a function from a child directive & using a variable in the parent directive

I have 2 directives:
Directive A which has a $scope.originalData variable that gets data from an http request, and also has a function to use that variable:
$scope.findStepEducatByActId = function(act_id){
console.info('findfindStepEducatByActId',$scope.originalData);
if(angular.isDefined($scope.originalData.connections)){
angular.forEach($scope.originalData.connections[0].con_detail,function(value,key){
if(value.act_id_from == act_id){
return value.educategory_from;
}
if(value.act_id_to == act_id){
return value.educategory_to;
}
});
}
};
Directive B (which is called flowChart) has this function passed to it in the HTML file template of A
<flow-chart findStepEducatByActId="findStepEducatByActId(act_id)"></flow-chart>
And I also am printing out $scope.originalData in that file: {{originalData}}
Directive B is simply calling that function:
angular.module('slmFlowClass').directive('flowChart', [function() {
return {
restrict: 'E',
templateUrl: 'scripts/modules/slmFlowClass/FlowClass.FlowChart.Template.html',
replace: true,
scope: {
findStepEducatByActId: '&'
},
link: function($scope, $element, $attrs) {
$scope.showNodeTooltip = function($event, node){
$scope.findStepEducatByActId('708663');
}
}
When I run this, I get a log: findfindStepEducatByActId undefined, but in HTML $scope.originalData I can see the data this variable contains.
So my question is, why when I call this function from B the $scope.originalData is null?
Use angular directive's 'require' property.
In your directive B,
return {
restrict: 'E',
templateUrl: 'scripts/modules/slmFlowClass/FlowClass.FlowChart.Template.html',
replace: true,
require: 'A'
....
For more info about this, please refer angular documentation for directive. https://docs.angularjs.org/guide/directive

binding data in a directive returns inconsistent values

i have this wierd problem with binding data to a directive. this is how i declare my directive:
<my-directive data="myArray"></my-directive>
my directive code looks like:
angular.module('ngApp')
.directive('myDirective', function () {
return {
scope:{
data: '='
},
template: '<div steps="data.length"></div>',
restrict: 'E',
link: function postLink(scope, element, attrs) {
console.log(scope);
console.log(scope.data);
}
};
});
in the first log, the data property is correct:
screenshot of console.log output
but the second log is undefined.
any idea why?
here is your solution :
<my-directive data-example="myArray"></my-directive>
you should always name your variables data-<name>. This is far easier to maintain and this prevent errors with keywords like this one ;)
angular.module('ngApp')
.directive('myDirective', function () {
return {
scope:{
data: '=example'
},
template: '<div steps="data.length"></div>',
restrict: 'E',
link: function postLink(scope, element, attrs) {
console.log(scope);
console.log(scope.data);
}
};
});
i hope this help,
Live example : JsFiddle
thanks to #hadiJZ and #Unex i figured it out:
my directive was nested in another directive. but the parent directive used the link function for the logic, since on creation it wasn't having child directives.
so moving the logic out to a controller solved my problem.
i figured it out when i added a $timeout to the child directive, and the log (scope.data) was correct.

AngularJS - Is it possible to pass attr value in Directive link function directly to template?

I was wondering if its possible to access attrs that were passed into a custom directive directly within the template config? So something like this... which currently isn't working?
angular.module('msDirectives', [])
.directive('msPerson', function(){
return{
restrict: 'E',
link: function(scope, element, attrs){
},
template: '<h1>{{attrs.firstName}}</h1>',
};
});
I realize I could assign attrs.firstName to scope within the link function to get this to work (like the following), just trying to understand whether scope is the only thing accessible within the template or whether attrs also get passed to it.
angular.module('msDirectives', [])
.directive('msPerson', function(){
return{
restrict: 'E',
link: function(scope, element, attrs){
scope.name = attrs.firstName;
},
template: '<h1>{{name}}</h1>'
};
});
The purpose of isolated scope (besides the isolation itself) is the assignment of attribute values to scope.
angular.module('msDirectives', [])
.directive('msPerson', function(){
return{
restrict: 'E',
scope: {
name: '#firstName'
},
template: '<h1>{{name}}</h1>'
};
});

How to add attributes of element to angular directive

I'm new to angular. I want to write a directive which has all the attributes that I added to it when using in html. For example:
This is my directive
'use strict';
app.directive('province', function($compile) {
return {
restrict: 'E',
link: function (scope, element, attrs, controller) {
var markup = "<select></select>";
var elem = angular.element(element);
elem.replaceWith($compile(markup)(scope));
}
};
})
HTML:
<province class="form-control" data-target"elemntId"></province>
I want my <select> contain the class and other attributes that I added to directive in html.
output that I want: <select class="form-control" data-target="elementId"></select>
I used angular.element(element).attr(attr);, but it does not worked;
Any help is appreciated in advance.
Edit
I want all the attributes that exist in attrs of link function to be added to markup.
I would iterate over directive's attr array and apply it to your template:
app.directive('province', function($compile) {
return {
restrict: 'E',
replace:true,
template: "<select></select>",
link: function (scope, element, attrs) {
var attr;
for (attr in attrs.$attr) {
if(attrs.hasOwnProperty(attr)){
element.attr(attr, attrs[attr]);
}
}
}
};
})
Directive Tag:
<province foo="bar" foo1="bar1"></province>
Compiled into:
<select foo="bar" foo1="bar1"></select>
Plunkr
Depending on your needs, you don't need to compile yourself. You can use template and replace instead.
app.directive('province', function() {
return {
restrict: 'E',
template: '<select></select>',
replace: true,
link: function (scope, element, attrs) {
}
};
});
See plnkr
You can make use of the attrs parameter of the linking function - this will get you the values of the attributes:
attrs.class and attrs.dataTarget are the ones you need.
You can take a look at the documentation here that elaborates further uses of the linking function

How can I get my directive to access the controllers scope

I have a setup like this:
<controller>
<directive>
in my controller that has a function that returns an html string. How can I get my directive to render this by accessing the controllers scope?
Or maybe I should just put the controller in the directive?
app.controller('controller', ['$scope', 'DataService', function ($scope, DataService) {
$scope.parseJson = function () {
//returns the html
};
}]);
directive
app.directive('Output', function () {
return {
restrict: 'A',
replace: true,
template: '<need html from controller>',
link: function(scope, element, attr) {
//render
//scope.parseJson();
}
};
});
You should use the isolated scope: '&' option
app.directive('output', ['$sce', function ($sce) {
return {
restrict: 'A',
replace: true,
template: "<div ng-bind-html='parsed'></div>",
scope:{
output: "&"
},
link: function(scope){
scope.parsed = $sce.trustAsHtml(scope.output());
}
};
}]);
Template:
<div output="parseJson()"></div>
The directive and the controller should be sharing the scope already. Don't bother using a template for the directive, just get the HTML string in you linking function (you already have the method call in there) and modify the element directly using element.html(). Take a look at the element docs for more info.
app.directive('Output', function ($compile) {
return {
restrict: 'A',
link: function(scope, element, attr) {
var templateString = scope.parseJson();
var compiledTemplate = $compile(templateString)(scope);
compiledTemplate.appendTo("TheElementYouWishtoAppendYourDirectiveTo");
}
};
});

Resources