Passing arguments to nested directives in Angular - angularjs

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

Related

Function inside directive not being triggered

Why my function toggleCategory function is not being triggered?
Directive
app.directive('asideFilter', function() {
return {
restrict: 'E',
scope: {
toggleCategory: '=&onToggleCategory'
},
transclude: true,
templateUrl: 'assets/directives/asideFilter/asideFilter.html',
link: function(scope, element, attrs){
}
};
});;
Directive template
<div ng-click="toggleCategory({id: 'teste'})">TEST</div>
Parent scope
$scope.onToggleCategory = function () {
console.log('onToggleCategory');
}
Parent Caller
<aside-filter toggle-category="onToggleCategory({id: 'test '})" categories="categories" />
You can call the parent controller function like this also
app.directive('asideFilter', function() {
return {
restrict: 'E',
scope: {
toggleCategory: '&',
},
transclude: true,
templateUrl: 'assets/directives/asideFilter/asideFilter.html',
link: function(scope, element, attrs){
scope.toggleCategoryClick = function (value) {
scope.toggleCategory(value);
}
}
};
});
Directive template
<div ng-click="toggleCategoryClick({id: 'teste'})">TEST</div>
Directive Element
<aside-filter toggle-category="onToggleCategory({id: 'test '})" categories="categories" />

How do I update a scope attributes in the link method?

This code is just a test that I'm putting together so I can understand the logic.
Basically what I want to happen is to get a value passed into the directive. Based on that value, I want to add several attributes to the scope.
This first test is just to update the attribute that was already passed in.
Directive:
angular.module('bd.common')
.directive('bdPopoverLegend', function () {
return {
restrict: 'AE',
replace: true,
scope: {
legendInfo: '=info'
},
templateUrl: '/bd/common/ctl/bdPopoverLegend.html',
link: function (scope, element, attrs) {
scope.legendInfo.test = 'hello world 4';
}
};
});
Template:
<div>{{legendInfo.test}}</div>
Calling the Directive:
<div bd-popover-legend="" info="{test: 'hello world 3'}">
The value never changes, it stays as 'hello world 3' and not 'hello world 4'
Try this:
.directive('bdPopoverLegend', function () {
return {
restrict: 'AE',
replace: true,
scope: {
legendInfo: '=info'
},
templateUrl: '/bd/common/ctl/bdPopoverLegend.html',
link: function (scope, element, attrs) {
scope.$watch('legendInfo', function (watchInfo) {
watchInfo.test = 'hello world 4';
});
}
};
});

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"
};
}])

AngularJS - Share ngModel with nested directives and transcluded directives

I am trying to create 3 directives:
.directive('dirOne', function () {
return {
restrict: 'E',
transclude: true,
replace: true,
controller: function ($scope, $element, $attrs) {
this.add = function (tag) {
tag && $scope.tags.push(tag);
};
},
template: '<div><p>Bucket from directive: {{tags}}</p><div ng-transclude></div></div>'
};
})
.directive('dirTwo', function () {
return {
restrict: 'A',
replace: true,
require: '^dirOne',
link: function (scope, element, attrs, dirOne) {
scope.add = function (tag) {
dirOne.add(tag);
};
},
template: '<div>'+
' <input type="text" ng-model="query" datum="sugestions" dir-three>' +
' <button ng-click="add(query)">add</button>' +
'</div>'
};
})
.directive('dirThree', ['$compile', function ($compile) {
var itemsTemplate = '<span class="sugestions"><span ng-repeat="item in datum|filter:query">{{item.name||item}}</span></span>';
return {
restrict: 'A',
transclude: true,
replace: true,
require: 'ngModel',
scope: {
datum: '=',
query: '=ngModel'
},
link: function (scope, element, attrs) {
var parent;
element.wrap('<span>');
parent = element.parent();
parent.append(angular.element($compile(itemsTemplate)(scope)));
}
};
}])
In the dirTwo and dirThree, I have an input <input type="text" ng-model="query" datum="sugestions" dir-three> with ngModel, this input needs to access and modify the content of ngModel, so that the scope is not isolated.
http://jsfiddle.net/joaoneto/hbABU/3/
Update
I Updated version, fix some mistakes I had committed, the content that was being transcluded in dirTwo, should not have the "ADD" function, and belongs to dirTree, hope it helps someone and apologize for peopl take to update this entry... see in http://jsfiddle.net/hbABU/4/

Accessing parent's parent controllers through Angular require attribute

In the below example, the accordion-group directive shares a controller and scope with the parent accordion, using the "require: '^accordion'" attribute within the accordion-group directive.
If I wanted to create a child directive, under accordion-group, how would it access the accordion controller as well? Requiring ^accordion and ^accordionGroup do not seem to work.
https://github.com/angular-ui/bootstrap/blob/master/src/accordion/accordion.js
It does work that way. I was just being stupid.
Fiddle for posterity here.
'use strict';
angular.module('myApp', []).controller('OneController', function() {
this.test = function(element) {
element.css('color', 'red');
}
}).directive('one', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
controller: 'OneController',
template: '<span ng-transclude>And a </span>',
}
}).directive('two', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
require: '^one',
template: '<span ng-transclude>and a </span>',
}
}).directive('three', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
require: '^one',
template: '<span ng-transclude>and a one two</span>',
link: function(scope, element, attrs, ctrl) {
ctrl.test(element);
}
}
});

Resources