Inner directive is executed first - should be second - angularjs

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

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" />

Can't require directive in modlule

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.

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

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');
}
}
};
});

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/

Resources