Take a controller of Angular directive - angularjs

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.

Related

How to call one controller array in another controller

I have created countryApp module. I have created "names" array in aboutCtrl.
I want to access "names" array in contactCtrl in insertContact function.
var countryApp = angular.module('countryApp', ['ngRoute']);
countryApp.config(function($routeProvider) {
$routeProvider.
when('/', {
template: '<h1>Home</h1>',
controller: 'homeCtrl'
}).
when('/aboutus', {
templateUrl: 'aboutus.html',
controller: 'aboutCtrl'
}).
when('/contact', {
templateUrl: 'cotacts.html',
controller: 'contactCtrl'
}).
otherwise({
redirectTo: '/'
});
});
countryApp.controller('homeCtrl', function($scope) {
});
countryApp.controller('aboutCtrl', function($scope) {
$scope.names = [{name:'venu',number:'22222',sex:'male'},{name:'Aishu',number:'1111',sex:'female'},{name:'Milky',number:'2222',sex:'female'}]
});
countryApp.controller('contactCtrl', function($scope) {
$scope.greeting = 'Hello, World!';
$scope.insertContact = function () {
alert(names);
}
$scope.resetContact = function () {
}
});
To expand on Claies' solution with actual code:
countryApp.controller('aboutCtrl', function($scope, dataService) {
/* If you're binding the values into your HTML,
you need to $watch the service variable 'names' */
$scope.$watch(function() { return dataService.names }, function() {
$scope.names = dataService.names;
});
dataService.names = [{name:'venu',number:'22222',sex:'male'},{name:'Aishu',number:'1111',sex:'female'},{name:'Milky',number:'2222',sex:'female'}]
});
countryApp.controller('contactCtrl', function($scope, dataService) {
/* You can place the same watch as in aboutCtrl here if
you're displaying stuff in HTML that's related to this controller */
$scope.greeting = 'Hello, World!';
$scope.insertContact = function () {
alert(dataService.names);
}
$scope.resetContact = function () {
}
});
countryApp.service('dataService', function() {
var dataObj = {};
dataobj.names = [];
return dataObj;
});
Do notice the comments about $watching the service variable; if you want to display the values in the view through a $scope variable, you'll need to $watch the corresponding service variable or the $scope variable won't be updated when the value of the service variable changes.
If you want to communicate between two controllers, then please take reference of the following fiddle:
Fiddle : http://jsfiddle.net/VaibhavP17/nky45/
It shows how to communicate between the two controllers and also the nuances of events. I hope this helps :)

Why variable is not available in controller?

I have HTML code:
<div ng-controller="ProfileLeftMenu">
<li ng-class="{'active':selectedTab == 'personal'}" ng-click="selectedTab = 'personal'" class="">Personal
</li>
</div>
And controller:
$scope.selectedTab = 'first';
if ($routeParams.page) {
ajax.get(page, function (CbData) {
$scope.selectedTab = page;
});
}
So, if do:
{{selectedTab}}
in template HTML get always: first
You need to update your $scope variable with the new $routeParams just after the change in route. For that you can listen for the$routeChangeSuccess event. Try this:
DEMO
app.js
var app = angular.module('plunker', ['ngRoute']);
app.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/test/:page', {
templateUrl: function(params) {
return 'pidat.html';
},
controller: 'MainCtrl'
});
}
]);
app.controller('MainCtrl', ['$scope', '$http', '$routeParams', function($scope, $http, $routeParams) {
// when controller is loaded params are empty
console.log('on controller load $routeParams', $routeParams);
$scope.name = 'World';
// only after you have transitioned to the new
// route will your $routeParams change so we
// need to listen for $routeChangeSuccess
$scope.$on('$routeChangeSuccess', function(){
console.log('on $routeChangeSuccess load $routeParams', $routeParams);
if ($routeParams.page) {
$scope.name = $routeParams.page;
}
});
}]);
So for your original example you would probably have to do something like this:
$scope.selectedTab = 'first';
$scope.$on('$routeChangeSuccess', function(){
if ($routeParams.page) {
ajax.get(page, function (CbData) {
$scope.selectedTab = page;
});
}
});
Use the angular $http service ($http.get()), not ajax.get(). Otherwise, Angular isn't aware of the change you make to the scope once the HTTP response comes and the callback is executed, unless you call $scope.$apply().

Inject dependency to controller called by directive

I would like to know if it is possible (if it is, so how? :)), to inject a dependency to a controller called by a directive.
I have a controller controller called MyCtrl. Here is his signature:
app.controller('MyCtrl', function ($scope, dataService, aDependency){...}
This Controller is usually defined in my route:
.segment('myPage', {
templateUrl: templatesUrl + 'mypage.html',
resolve: {
aDependency: ['$q', 'dataService', '$location', function ($q, dataService, $location) {
var defer = $q.defer();
dataService.retrieveCCData(defer, $location);
return defer.promise;
}],
},
controller: 'MyCtrl'
})
But now, I would also like to call this controller from a directive.
Problem is that I don't know How to inject the aDependency.
It said that the provider is unknown.
Here's my directive:
app.directive('gettingStarted1', ['dataService', function (dataService) {
return {
restrict: 'E',
templateUrl: templatesUrl + 'mypage.html',
controller: 'MyCtrl',
//resolve: {
//datasources: ['dataService', function (dataService) {
//return null;
//}]
//}
};
}]);
Resolve is impossible in directive.
Some help will be appreciate
Thank you
Make aDependency a separate service.
app.provider('aDependency', function () {
this.$get = ['$q', 'dataService', '$location', function ($q, dataService, $location) {
var defer = $q.defer();
dataService.retrieveCCData(defer, $location);
return defer.promise;
}];
});
You can resolve it with
resolve: {
'aDependency': 'aDependency',
}
or
resolve: ['aDependency'];
you could use the controller Function from the directive
.directive("sampledirective", function (dependancy1, dependancy2, ....) {
return {
scope: '=',
controller: function ($rootScope, $scope) {
//DO your controller magic here where you got your scope stuff
}
}
})
One thing i learned it seems the $scope values arent immediatly updated from directive to Controller. If you use objects like
$scope.smth.smth = 'test'
It gets updated immediatly else you would need to $apply

Angular [$injector:unpr] Unknown provider with customize directive

I have a little issue by using a customize directive within the template field of UI-Bootstrap modal directive.
My aim is send data to modal via resolve attribute and re-use these resolved parameters inside the controller of my own directive.
var app = angular.module('app', ['ui.bootstrap']);
app.controller('MyCtrl', ['$scope', '$modal', function($scope, $modal) {
$scope.openModal = function () {
var popup = $modal.open({
template: '<my-modal></my-modal>',
resolve : {
mydata : function() {
return 42;
}
}
});
};
}]);
app.controller('ModalController', ['$scope', 'mydata', function($scope, mydata) {
//The error is in this directive controller
$scope.mydata = mydata;
}]);
app.directive('myModal', function() {
return {
restrict: 'E',
templateUrl : 'mymodal.html',
controller : 'ModalController',
replace: true
};
});
Maybe I proceed in the wrong way.
Any suggest to make this code functionnal ?
http://plnkr.co/edit/RND2Jju79aOFlfQGnGN8?p=preview
The resolve parameters are only injected to the controller defined in the $modal.open config parameters, but you want to inject it to the directive controller. That will not work. Imagine you would use the myModal directive somewhere else, there wouldn't be a myData object that could be used.
But i don't realy see, what you need the directive for. You could go much easier this way:
app.controller('MyCtrl', ['$scope', '$modal',
function($scope, $modal) {
$scope.openModal = function() {
var popup = $modal.open({
templateUrl: 'mymodal.html',
controller: 'ModalController',
resolve: {
mydata: function() {
return 42;
}
}
});
};
}
]);
// Here the mydata of your resolves will be injected!
app.controller('ModalController', ['$scope', 'mydata',
function($scope, mydata) {
$scope.mydata = mydata
}
]);
Plunker: http://plnkr.co/edit/bIhiwRjkUFb4oUy9Wn8w?p=preview
you need to provide an Object "mydata". Ensure, that you have a correct implemented factory which provides your myData Object. If you had done that, you can "inject" your myData Object where ever you want to.
yourApp.MyDataFactory = function () {
var myData = {i: "am", an: "object"};
return myData;
}
this would provide an "myData" Object
I'm not sure what you are trying to accomplish with the directive, but if you are trying to provide a generic way to invoke the $model, that you can then use from many places in your app, you may be better off to wrap $model with a service. Than you can then call from other places in your app.
I forked and modified your plunkr to work this way: http://plnkr.co/edit/0CShbYNNWNC9SiuLDVw3?p=preview
app.controller('MyCtrl', ['$scope', 'modalSvc', function($scope, modalSvc) {
var mydata = {
value1: 42
};
$scope.openModal = function () {
modalSvc.open(mydata);
};
}]);
app.factory('modalSvc', ['$modal', function ($modal) {
var open = function (mydata) {
var modalInstance,
modalConfig = {
controller: 'ModalController',
resolve: {
mydata: function () {
return mydata;
}
},
templateUrl: 'mymodal.html'
};
modalInstance = $modal.open(modalConfig);
return modalInstance;
};
return {
open: open
};
}]);
Also, I changed mydata to be an object, rather than '42', as I am sure you will have other data to pass in. the markup was updated accouringly:
<div class="modal-body">
BODY {{mydata.value1}}
</div>
Doing it this way, the resolve property works, and you can get your data.
As for the other answers mentioning you must define mydata, the resolve property passed into $model does this for you, so it can be injected into the modal's controller (ModalController), like you have done.

Access angular controller from directive

When I have a controller inside my html
<div ng-controller="myController" id="myCtrl">...</div>
I can access it via:
angular.element(myCtrl).controller()
But how can I access the controller from a directive?
directive('myDirective', function () {
return {
...
templateUrl: '/Views/myview.html',
controller: myController
}
})
This controller should be defined the same module module where your directive is defined:
E.g
angular.module('myModule', [])
.controller('myController',['$scope', function($scope){
$scope.myData = {'someData':1337};
}])
.directive('myDirective', [function(){
return {
...
templateUrl: '/Views/myview.html',
controller: 'myController'
}
}])
Here is a plunkr, demonstrating that way:
http://plnkr.co/edit/UDCWUI5EMlfoXb9u3GYh?p=preview
And here is a plunkr, demonstrating having a directive in a module using a controller that is defined in another module:
http://plnkr.co/edit/Gg0BzKPOqO2NnTgf3Hkr?p=preview
angular.module('myApp',[
])
.controller('MyController', ['$scope', function($scope){
$scope.someValue = 'someValueFromController';
}])
angular.module('otherModule', ['myApp'])
.directive('myDirective', [function(){
return {
restrict: 'E',
templateUrl: 'someTemplate.html',
controller: 'MyController'
}
}])
Alternatively, you can use the $controller service to instantiate your controller with the appropriate stuffs and use it everywhere (from every module that imports the module where your controller is defined).

Resources