How can I access variables within another function?
myApp.controller "RegistrationsController", ($scope, $location, $http, $modal)->
$scope.open = () ->
# move to global
modalInstance = $modal.open(
templateUrl: "/assets/angular/templates/registrations/_signup.html",
controller: "ModalController"
)
$scope.cancel = ->
modalInstance.dismiss('cancel')
$scope.saveUser = () ->
$scope.cancel()
From the code above I'm trying to dismiss the modalInstance (modal opened) via cancel function.
However, I guess I need to make modalInstance a global variable first?
declare modalInstance outside of the functions. This will scope it to the whole controller.
myApp.controller "RegistrationsController", ($scope, $location, $http, $modal)->
var modalInstance;
$scope.open = () ->
# move to global
modalInstance = $modal.open(
templateUrl: "/assets/angular/templates/registrations/_signup.html",
controller: "ModalController"
)
$scope.cancel = ->
modalInstance.dismiss('cancel')
$scope.saveUser = () ->
$scope.cancel()
If you're trying to cancel from the ModalController then you can add inject the $modalInstance dependency like ...
.controller('ModalController', function($scope, $modalInstance) {
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
});
If you're trying to cancel it from anywhere else then you can share you're controller among other directives using require? Like
.directive('otherDirective', function() {
return {
require: 'RegistrationController',
link: function(scope, el, attr, ctrl) {
}
}
});
Or you could use a service as mediator between other controllers, services, directive, what ever.
.service('mediator', function() {
var modalInstance;
this.modalInstance = function(instance) {
if (instance) {
modalInstance = instance;
}
return modalInstance;
};
});
and then in your directives and controllers and what not, do something like...
.controller('SomeController', function(mediator) {
this.cancel = function() {
mediator.modalInstance().dismiss('cancel');
});
});
You can amend for CoffeeScript ;)
Related
I want to use same modal window with different parent controller, the only difference in modal controller is separate factories that i am calling e.g Ctrl-1-Factory.getServerFiles so similarly i want to call Ctrl-2-Factory when modal populated for Ctrl2.
ModalCtrl.js
angular.module('App').controller('ServerFilesCtrl', function($scope, $rootScope, FileSaver, $uibModalInstance, Ctrl-1-Factory, $uibModal) {
'use strict';
$scope.cancel = function() {
$uibModalInstance.close();
}
Ctrl-1-Factory.getServerFiles().then(function(response) {
$scope.data = response.data;
console.log($scope.data);
});
});
Ctrl-1.js
$scope.modalInstance = $uibModal.open({
templateUrl: '/web/global/modal.html',
controller:'ModalController'
});
Ctrl-2.js
$scope.modalInstance = $uibModal.open({
templateUrl: '/web/global/modal.html',
controller:'ModalController'
});
You can wrap it in a service method.
angular.module('App').factory('FilesModal', function() {
return {
openModal: openModal
};
function openModal() {
return $uibModal.open({
templateUrl: '/web/global/modal.html',
controller: 'ModalController'
});
}
});
angular.module('App').controller('Ctrl1', function(FilesModal) {
$scope.someEventFunction = someEventFunction;
function someEventFunction() {
$scope.modalInstance = FilesModal.openModal();
}
});
Pass in arguments as needed to make it more robust
When I am trying to open a modal on ng-click the scipe variables is getting lost.
var modalInstance = $modal.open({
templateUrl: 'partials/create.html',
controller: 'AppCreateCtrl',
scope: $scope // <-- I added this
});
You should pass data using the resolve property like this:
var modalInstance = $modal.open({
templateUrl: templateSrv.templateUrl('partials/create.html'),
controller: modalBootstrap,
backdrop: 'static',
keyboard: false,
resolve: {
data: function () {
var result = {};
result.scope = $scope;
return result;
}
}
});
modalInstance.result.then(
function (dataPassedFromModalConroller) {
//this is called when the modal is closed
},
function (dataPassedFromModalConroller) { //Dismiss
//this is called when the modal is dismissed
}
);
Specify the controller for the modal instance like this (we do this in another file):
var modalBootstrap= function ($scope, $modalInstance, data) {
$scope.modalInstance = $modalInstance;
$scope.scope = data.userId;
};
modalBootstrap['$inject'] = ['$scope', '$modalInstance', 'data'];
Your modal template would look something like this:
<div ng-controller="AppCreateCtrl">modal content here</div>
I am trying to hook up an Angular Bootstrap modal (pop-up) but it's giving me either "templateUrl" not found error, or this error: Error: [ng:areq] http://errors.angularjs.org/1.3.15/ng/areq?p0=ModalInstanceCtrl&p1=not%20a%20function%2C%20got%20undefined
I just want some theoretical suggestions on why that would be the case. I have tried a lot of things: it's all properly hooked up, all the spelling matches, etc, etc.
$modal is being used in the controller with other functions as well, so it's all being injected.
Angular Documents provide a suggestion that when you get this error it is possible that you have a controller being injected into another controller. Which is exactly what was happening with my attempt to add a modal as their box solution:
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $modal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.animationsEnabled = true;
$scope.open = function (size) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$scope.toggleAnimation = function () {
$scope.animationsEnabled = !$scope.animationsEnabled;
};
});
controller: 'ModalInstanceCtrl' MUST BE removed from your modal function if you're adding it to an existing controller, otherwise it will all go to ... you know where.
Can be as simple as the controller not existing on your module.
I forgot to add the code for the modal controller :( when I first tried it in my project
This controller is about 3 controllers deep in my project (make sure your using "controller AS cntlr" style) so embedding wasn't a problem for me.
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
$uibModalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
});
I'm trying to pass an object into a modal dialog in a bootstrap/angularJS using the code below. I did this in the style of the answer given at AngularJS UI Bootstrap modal is unable to perform functions from scope. When the modal form is supposed to open from a call to editGroup(), I get the following error:
Error: [$injector:unpr] Unknown provider: selGroupProvider <- selGroup
var EditGroupModalController = function ($scope, $modalInstance, selGroup) {
$scope.user = $sessionStorage.user;
$scope.selGroup = selGroup;
$scope.closeModal = function () {
$modalInstance.close();
};
};
$scope.editGroup = function (selGroup) { // "selGroup" receives the current Group object from $scope.groupList[]
$modal.open({
templateUrl: 'app/views/administration/advanced/editgroup.html',
controller: ['$scope', '$modalInstance','$modal','$sessionStorage','advancedService','selGroup', EditGroupModalController],
size: 'lg',
windowTemplateUrl:'app/views/partials/modaltemplatedraggable.html',
backdrop:'static',
resolve: {
item: function () {
return selGroup;
}
}
});
};
The official description of this error is here; however, I do not understand why I am receiving this error. Any help with this would be greatly appreciated.
Your controller's dependencies list doesn't match controller's function definition: in $modal.open you've listed six dependencies, while in function only three are present.
Dependencies are injected by resolve keys - in your case the key is item.
Necessary changes to your code in order to make it work:
Replace (1)
var EditGroupModalController = function ($scope, $modalInstance, selGroup)
with
var EditGroupModalController = function ($scope, $modalInstance, $modal, $sessionStorage, advancedService, selGroup)
And replace (2)
resolve: {
item: function () {
With
resolve: {
selGroup: function () {
You should name the variable in the resolve as 'selGroup' instead of 'item' so that it can be correctly injected.
Also, the names of the declared dependencies should match the function definition. I put together this simple demo.
angular.module('test', ['ui.bootstrap']).controller('TestController', function($scope, $modal) {
var sel = {name: "A group"};
var EditGroupModalController = function($scope, $modalInstance, selGroup) {
$scope.selGroup = selGroup;
$scope.closeModal = function() {
$modalInstance.close();
};
};
$scope.editGroup = function(selGroup) { // "selGroup" receives the current Group object from $scope.groupList[]
$modal.open({
template: '<div>Test {{selGroup.name}}</div>',
controller: ['$scope', '$modalInstance', 'selGroup', EditGroupModalController],
size: 'lg',
backdrop: 'static',
resolve: {
selGroup: function() {
return sel;
}
}
});
};
});
http://plnkr.co/edit/ec1PjkDZtf4yqINONnX5?p=preview
I'm unit testing one of my directives. Its basic structure is like this
angular.module('MyApp')
.directive('barFoo', function () {
return {
restrict: 'E',
scope: {},
controller: function ($scope, $element) {
this.checkSomething = function() { .... }
},
link: function(scope, element) { .... }
}
});
In my unit test I want to test the function 'checkSomething', so I tried
var element = $compile('<barFoo></barFoo>')(scope);
var controller = element.controller()
...
However, controller is undefined. Is it possible to access the controller of the directive ?
the glue is your scope so you can do
controller: function ($scope, $element) {
this.checkSomething = function() { .... }
$scope.controller = this;
},
but i think it would be best practice to attach every function to the scope like
controller: function ($scope, $element) {
$scope.checkSomething = function() { .... }
},
and then its
var element = $compile('<barFoo></barFoo>')(scope);
var checksomthingResult = scope.checkSomething ()