Variable Undefined in Directive with isolated scope - angularjs

I created a directive with isolated scope. selectedcontractguid is passed to the directive via html.
when I console.log $scope in directive, it shows me selectedcontractguid along with correct guid.
But when I try to access $scope.selectedcontractguid in directive controller, it logs undefined.
Anyone know why? please take a look at following example.
<instalments-box selectedcontractguid="instalment.contract.guid"> </instalments-box>
angular.module('app')
.directive('instalmentsBox', ['InstalmentService', function(InstalmentService) {
return {
templateUrl:'scripts/directives/contracts/instalments-box.html?v='+window.app_version,
restrict: 'E',
scope: {
selectedcontractguid: '='
},
controller: function($scope) {
console.log($scope.selectedcontractguid);
}
}
}]);

Try this one may be $watch help you out :
angular.module('app')
.directive('instalmentsBox'['InstalmentService', function(InstalmentService) {
return {
templateUrl:'scripts/directives/contracts/instalments-box.html?v='+window.app_version,
restrict: 'E',
scope: {
selectedcontractguid: '=selectedcontractguid'
},
controller: function($scope,$watch) {
$scope.$watch('selectedcontractguid', function (watch) {
console.log(watch);
})
}
}
}]);

Related

Access $scope from within $scope.$on

I have this code:
.directive('hostelGridBed', function($rootScope){
return {
restrict: 'E',
scope: {
config: '=',
range: '=',
days: '='
},
link: function(scope, element){
},
controller: ['$scope', function($scope){
$scope.innerStay = '';
function switchStay(data){
$rootScope.$broadcast('SwitchStay', {data: data.config});
};
$scope.onDropComplete = function(data,evt){
//$rootScope.$broadcast
switchStay(data);
console.log('Drop completo bed!');
}
}],
templateUrl: './js/templates/hostelgridbed.html'
}
})
.directive('hostelGridDay', function(StaysFactory){
return {
restrict: 'E',
scope: {
config: '=',
date: '='
},
link: function(scope,element){
},
controller: ['$scope','$rootScope', function($scope,$rootScope){
$scope.switchStay = function(evt, data){
console.log(data);
// Here. How can I access this controller's $scope
}
$scope.$on('SwitchStay', $scope.switchStay);
}],
templateUrl: './js/templates/hostelgridday.html'
}
})
I get data from $broadcast ok, it's all good. Except that I need to access the directive's $scope from within $scope.switchStay function.
Is there a way to accomplish that?
Actually when you $broadcast or $emit the event from the directive, you could send also the directive's scope as parameter. It should work, but this is actually awful and a really bad practice.
What you have to do in these cases is to add a callback parameter to the directive (&) and provide the switchStay function as callback, and simply trigger it from the directive, passing the parameters that you need to access inside the function.
I hope it makes sense.

Cant use directive controller values in directive template

Im having a hard time accessing the attributes passed in to my directive from the template of that directive. I want to be able to access 'companyId' from album.tmpl.html but no matter what i try i can't get it. The strangest part is i can see it has made its way in to the controller, but somehow it's not getting from the controller to the template. I know the template is correctly calling the controller as it can succesfully print out the value of 'testVar' which is initialised inside the controller. Any advice would be appreciated.
directive + directive controller
(function () {
'use strict';
angular.module('erCommon')
.directive('erAlbum', albumDirective)
.controller('AlbumController', AlbumController);
function AlbumController() {
var vm = this;
vm.testVar = "test var initiated";
}
function albumDirective($log) {
function albumLink(scope, element, attrs, AlbumController) {
//watch vars in here
}
return {
restrict: 'E',
scope: {
companyId: '=companyId'
},
bindToController: true,
templateUrl: 'components/temp/album.tmpl.html',
controller: 'AlbumController',
controllerAs: 'albumCtrl',
link: albumLink
};
}
})();
template ( album.tmpl.html
<div ng-controller="AlbumController as albumCtrl">
testVar: {{albumCtrl.testVar}}<BR>
companyId:{{albumCtrl.companyId}}<BR>
</div>
usage
<er-album company-id="2"></er-album>
output
test var: test var initiated
companyId:
You need to remove ng-controller from your template:
<div>
testVar: {{albumCtrl.testVar}}<BR>
companyId:{{albumCtrl.companyId}}<BR>
</div>
To achieve the result you wanted i had to modify the structure of your code slightly. Hope this helps you to understand the issue. Look for materials about isolated scopes which Angular uses with directives.
HTML:
<div ng-app="erCommon" ng-controller="AlbumController as albumCtrl">
<er-album company-id="2" test = "albumCtrl.testVar"></er-album>
</div>
Controller:
angular.module('erCommon', [])
.directive('erAlbum', albumDirective)
.controller('AlbumController', AlbumController);
function AlbumController() {
var vm = this;
vm.testVar = "test var initiated";
}
function albumDirective() {
return {
restrict: 'E',
scope: {
test: '=test',
companyId: '#companyId'
},
template: '<div> testVar: {{test}}<BR> companyId:{{companyId}}<BR> </div>', // it will work fine with templateUrl as well, just didn't want to cr8 another file...
link: function(scope, element, attrs){
//do whatever else you might need;
}
};
}

inherit Angular parent directive attribute with isolate scope

I'm trying to inherit an attribute from a parent custom directive with isolate scope. In the example below, I want to be able to access the api attribute on myParent from the myChild controller or link function. My end goal is to inject an instance of the api that can be accessed by the children and from the view controller.
<my-parent api="parentInstance1">
<my-child ng-repeat="field in ::data"
ng-attr-src="{{field.src||undefined}}"
</my-child>
</my-parent>
<my-parent api="parentInstance2">
<my-child ng-repeat="field in ::data"
ng-attr-src="{{field.src||undefined}}"
</my-child>
</my-parent>
A simplified version of both directives looks like this
app.directive('myParent', function () {
return {
transclude: true,
restrict: "E",
scope: {
api: '=?'
},
template: '...',
controller: function ($scope, $attrs ) {
// foo is injected from a factory instance
function foo ( ) {
}
$scope.api = {
foo: foo
}
},
link: function ($scope, $element, $attr) {
}
}
});
app.directive('myChild', function () {
return {
require: "^myParent",
restrict: "E",
scope: {
api: '=?'
},
template: "...",
controller: function ( $scope ) {
// I want to access $scope.api in link or controller
},
link: function ($scope, $element, $attr) {
// I want to access $scope.api in link or controller
}
}
});
I can't access $scope.api from the child directive but $scope.parentInstance1 and $scope.parentInstance2 are visible. I realise I can just explicitly declare but I'd rather understand how to do it correctly.
I dont know why you are referencing parentInstance1 and parentInstance2 on my-parent but the attributes on my-child are in myParent's $scope so you can reference the actual $scope.api object that is on myParent's $scope in the attributes of the my-child directive tag and then reference the name of the attribute in the isolate scope definition of the myChild directive.
<my-child inner-api="api"></my-child>
.. and then in the child directive...
app.directive('myChild', function () {
...
scope: {
innerApi: '=?'
}
...
controller: function($scope) {
$scope.innerApi // <- accessible in the controller
}
Heres a simplified fiddle...

Angular: controller's methods are not working in directive's template

Here is a directive that is loading new Template from file:
.directive('candidatesFilter', function(){
return {
resctict: 'E',
replace: true,
templateUrl: 'views/directives/filters/AAAA.html'
}
})
Next HTML-element calls this directive from the other HTML-Template (e.g. xxx.html):
<candidates-filter></candidates-filter>
There is next controller for this parent Template (xxx.html):
app.controller('candidatesController', function($scope, $location ){
$scope.addPeson = function() {
$location.url('/candidate/0');
};
});
Method addPerson() is not accessible inside the Directive's template AAAA.html, because
data-ng-click="addPerson()"
is not working there. How to change the Directive to make addPerson() method available inside the directive's template?
TEMPORARY Solution
I fixed this issue by next solution
.directive('candidatesFilter', function(){
return {
resctict: 'E',
replace: true,
templateUrl: 'views/directives/filters/AAAA.html',
controller: function(){
$('button.add').on('click',function(){
location.hash = '#/candidate/0';
});
}
}
})
If I understand the problem correctly:
You can pass a function into the directive for it to use
<candidates-filter></candidates-filter>
becomes
<candidates-filter add-candidate="addPerson()"></candidates-filter>
and the directive definition changed as follows:
.directive('candidatesFilter', function() {
return {
resctict: 'E',
replace: true,
scope: {
addCandidate: '&addCandidate'
}
templateUrl: 'views/directives/filters/AAAA.html'
link: function(scope, element, attrs) {
scope.someFunctionInDirective = function() {
scope.addCandidate();
}
};
}
})
Alternatively you can call it with the ng-click like normal from the button
Hope this helps clarify it?

How to use isolated scope action with parameter from one directive to another

I have a directive I want to pass isolated scoped action with parameter from one directive to another. please see the Plunker.
plnkr
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.singleClick = function (test) {
alert('singleClick'+test);
}
});
app.directive('myButton', [function () {
return {
restrict: 'E',
template: '<input type="button" value="Click" ng-click="click("test")" />',
scope: { onSingleclick: '&singleclickFn' },
link: function (scope, iElm, iAttrs, controller) {
scope.click = function (test) {
alert('singleClick'+test);
scope.onSingleclick(test);
}
}
};
}]);
app.directive('myNewButton', [function () {
return {
restrict: 'E',
scope: { singleclick: '&singleclickFn' },
template: '<my-button singleclick-fn="singleclick(test)" />',
};
}]);
In controller method I have got parameter is undefined.
To pass data from directive with isolated scope to the parent scope pass an object as argument instead of the primitive. So in your myButton directive use something like
ng-click="click({inp:'test'})
and access the argument as object in the singleClick function of your controller.
In your plunkr i can see you pass the result of the function execution to you directive instead of the function itself. Therefore it is undefined as the function doesn't return anything.
use singleclick-fn="singleClick" to pass the funciton to your directive's scope.
Please make your plunkr work (I get errors in the console if i open it), so i can verify the error

Resources