Access AngularJs directive variable inside controller - angularjs

I'm little bit new to Angularjs. What I want is access "$scope.myVar" variable inside 'myController' controller. It would be great help if you can provide a solution.
angular.module('myDirective', [])
.controller('myController', ['$scope', function ($scope) {
}])
.directive('myDirective', function () {
return {
scope: {
myVar: '='
},
controller: function ($scope) {
$scope.myVar = 'xyz';
alert($scope.myVar);
}
};
});
<html lang="en-US">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script type="text/javascript" src="newjavascript.js"></script>
<body ng-app="myDirective">
<div ng-controller="myController">
<my-directive></my-directive>>
</div>
</body>
</html>

You just create a myVar variable in your controller and pass it to the directive using my-var attribute.
In your myController, Define myVar as
$scope.myVar= "Hello"
I your DOM, pass it to the directive as
<my-directive my-var="myVar"></my-directive>
Since you are using two way binding, any changes made to myVar by the directive are available in your controller.
You can put a watch on myVar to track the changes.

angular.module('myDirective', [])
.controller('myController', ['$scope', function ($scope) {
$scope.show = function() {
alert($scope.myVar);
};
}])
.directive('myDirective', function () {
return {
scope: {
myVar: '='
},
controller: function ($scope) {
$scope.myVar = 'xyz';
alert($scope.myVar);
$scope.$parent.myVar = $scope.myVar; // here you can access the controller scope by using $parent
}
};
});

Related

In AngularJS, if the child directive cannot access it's immediate parent's scope then would it inherit its nearest, non-isolated ancestor's scope?

I have two examples in favor of the above statement -
1) When using $scope (http://plnkr.co/edit/kFM77mVReS7AUwZsNzCV?p=preview) -
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script>
angular
.module('myApp', [])
.directive('directive1', function() {
return {
controller: ['$scope', function($scope) {
$scope.name = 'Directive1';
}]
};
})
.directive('directive2', function() {
return {
controller: ['$scope', function($scope) {
$scope.name = 'Directive2';
}],
scope: {}
};
})
.directive('directive3', function() {
return {
template: 'I am {{name}}'
};
});
</script>
</head>
<body ng-app='myApp'>
<directive1>
<directive2>
<directive3>
</directive3>
</directive2>
</directive1>
</body>
</html>
2) When using controllerAs(http://plnkr.co/edit/zmIRa1t87ZIMDS6X5rNo?p=preview)-
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script>
angular
.module('myApp', [])
.directive('directive1', function() {
return {
controller: function() {this.name = 'Directive1';},
controllerAs: 'ctrl1'
};
})
.directive('directive2', function() {
return {
controller: function() {this.name = 'Directive2';},
controllerAs: 'ctrl2',
transclude: true,
template: '<ng-transclude></ng-transclude>',
scope: {}
};
})
.directive('directive3', function() {
return {
template: 'I am {{ctrl1.name}}'
};
});
</script>
</head>
<body ng-app='myApp'>
<directive1>
<directive2>
<directive3>
</directive3>
</directive2>
</directive1>
</body>
</html>
The output of both the codes is - I am Directive1 which shows that directive3 inherits the scope of directive1(it won't access the scope of directive2 since it has an isolated scope) which proved me wrong in assuming that an isolated scope would break the inheritance chain between its parent directive and its child directives and thus none of its child directive would be able to access the scope of any of its ancestor directives.
Am I missing something here or is my concept of scope inheritance completely wrong?
The output <...> proved me wrong in assuming that an isolated scope would break the inheritance chain between its parent directive and its child directives
The proof itself is wrong. This behaviour is specific to template-less directives and is similar to transclusion. In the code above directive1 has no own scope, and $scope.name = 'Directive1' is set on root scope. And both directive1 and directive2 are compiled with root scope because they have no templates and no own scopes.
The said assumption will be correct if directives have their own templates, e.g.:
.directive('directive2', function() {
return {
template: '<directive3>'
controller: ['$scope', function($scope) {
$scope.name = 'Directive2';
}],
scope: {}
};
})
Use scope:true in all your 3 directives and it will able to access all scopes of the parents
Note: scope:true will inherit the properties from the parent, but scope:{} will not inherit the properties from the parent.
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script>
angular
.module('myApp', [])
.directive('directive1', function() {
return {
controller: ['$scope', function($scope) {
$scope.name = 'Directive1';
}],
scope: true
};
})
.directive('directive2', function() {
return {
controller: ['$scope', function($scope) {
$scope.name = 'Directive2';
}],
scope: true
};
})
.directive('directive3', function() {
return {
template: 'I am {{name}}',
scope: true
};
});
</script>
</head>
<body ng-app='myApp'>
<directive1>
<directive2>
<directive3></directive3>
</directive2>
</directive1>
<br>
<directive1>
<directive3></directive3>
</directive1>
<br>
<directive2>
<directive3></directive3>
</directive2>
</body>
</html>

How to pass data in angular-fancy-modal?

I am using angular-fancy-modal to display modals in my app.
This is my controller:
.controller('CategoryController', ['$scope', 'categoryService', '$fancyModal', function($scope, categoryService, $fancyModal) {
$scope.subcategories = {};
$scope.open = function() {
$fancyModal.open({
templateUrl: 'public/popupTmpl.html',
resolve: {
items: function() {
return $scope.subcategories;
}
}
});
};
}]);
The method ng-click calls method $open.
popupTmpl.html
<script type="text/ng-template" id="popupTmpl.html">
<div class="modal-header"> $$items$$
<div class="categories-list">
<span class="list-category-item">100</span>
</div>
</div>
</script>
In template: popupTmpl.html I tried to get items from resolve, but it does not work. How to pass data $scope.subcategories in template?
As far i understand from your question, It seems you need to display an variable $scope.subcategories from your parent controller CategoryController, to your Modal $fancyModal..
If i understood correct, just passing parent scope to your modal will resolve it..
$fancyModal.open({
templateUrl: 'public/popupTmpl.html',
scope: $scope,
resolve: {
items: function() {
return $scope.subcategories;
}
}
});
Using scope:$scope will pass the scope of the controller CategoryController to the Modal also. Thus, it will help you to use(pass) all the variables and functions within the CategoryController, in the fancyModal also..

angular js alert by click donot work

i am new to AngularJS so please forgive me this dump question.
i have error
Cannot set property 'test' of undefined
angularjs
var App = angular.module('StartModule', []);
App.controller('ModalDemoCtrl', [
function($scope) {
$scope.test = function() {
alert("12312");
}
}
]);
html
<body ng-app="StartModule">
<div ng-controller="ModalDemoCtrl">
<div ng-click="test()">11111</div>
</div>
<body>
You just miss $scope to controller's second argument:
var App = angular.module('StartModule', []);
App.controller('ModalDemoCtrl', [ $scope, function($scope) {
$scope.test = function() {
alert("12312");
}
}]);
You're missing the $scope dependency, you need to inject it in your controller :
App.controller('ModalDemoCtrl', ['$scope'
function($scope) {
That's why the $scope variable is undefined, you're not actually injecting any dependency in it.
This uses the Inline Array Annotation: https://docs.angularjs.org/guide/di

Take a controller of Angular directive

Consider we have some directive with templateUrl and controller.
angular.module('someApp').directive('myDirective', [function() {
return {
templateUrl:'someTemplate.html',
controller: ['$scope', function($scope) {
this.someFunction = function() {}
}]
}
}])
If we try to get controller now
var directive = angular.element('<my-directive />');
$compile(directive)( scope );
var controller = directive.controller('myDirective');
the controller is undefined.
The answer is to set a template instead of templateUrl in the directive.
angular.module('someApp').directive('myDirective', [function() {
return {
template:'<span>Solution!</span>',
controller: ['$scope', function($scope) {
this.someFunction = function() {}
}]
}
}])
I can't find anything about it in documentation. I think it's a bug.

Injecting $scope in manually instantiated controller

I'm trying to inject $scope in a controller created using the $controller service.
I'm getting the following error:
Unknown provider: $scopeProvider <- $scope <- TestController
It's important to mention that the creation is happening inside a directive's link function.
I've written a simple example to show the error.
app.js:
(function() {
angular.module('app', [])
.controller('TestController', [
'$scope',
function($scope) {
// I want to be able to use 'message' from the directive's template
// as if the controller was loaded directly using ng-controller
$scope.message = 'Hello World!';
}
])
.directive('directive', [
'$controller',
function($controller) {
return {
restrict: 'A',
template: '<div>{{ message }}</div>',
link: function(scope) {
// In the actual app the controller is dynamically selected
// I'm registering a $watch here that provides me the
// name of the controller
scope.myController = $controller('TestController');
}
};
}
]);
})();
index.html:
<!DOCTYPE html>
<html ng-app="app">
<head>
<title>Testing injection</title>
</head>
<body>
<div directive></div>
<script src="angular.js"></script>
<script src="app.js"></script>
</body>
</html>
Question: Why is this happening? Can you explain me the logic behind this behaviour? Any workaround?
Thank you.
Following Digix's answer, I was able to make it work:
var locals = {};
locals.$scope = scope;
$controller('TestController', locals);
My assumption is that in this way, instead of creating a new scope, the controller shares the one of the directive.
var locals = {};
locals.$scope = scope.$new();
$controller('testCtrl', locals);

Resources