AngularJS $modalInstance - Can i do this in one controller? - angularjs

I've spent some time having a play with the AngularJS Bootstrap popup, and for intents it's working great, but what i'd like to do is bind it, and it's dependant script to the same controller, what i can't get working is the close button now though. If i create a NEW controller, and inject $modalInstance it works great and i can wireup the close button without any issues at all, but i don't want a second controller, it seems to be over complication: i want all my controller logic in the formController really.
Why would i actually want two controllers? Passing the scope between two controllers just seems overkill to me, and the larger a project becomes the more un-managable it will become. Am i trying to over-simplify this unnecessarily? :)
The script:
(function(){
var app = angular.module('ngModalDemo', ['ui.bootstrap'])
.controller('formController', function($scope, $modal){
$scope.openModal = function () {
var modalInstance = $modal.open({
templateUrl: 'SomeModal.html',
controller: 'formController'
});
};
$scope.closeModal = function () {
// Code needed here :)
};
})
})();
The HTML body (excuse the HTML in script for the purposes of the DEMO):
<div ng-controller="formController">
<button class="btn btn-default" ng-click="openModal()">Let's do some stuff!</button>
<script type="text/ng-template" id="SomeModal.html">
<div class="modal-header">Do some stuff in this modal y'all.</div>
<div class="modal-footer">
<button class="btn btn-info" ng-click="closeModal()">Close</button>
</div>
</script>
</div>
The answer based on Kaspars' input :)
(function(){
var app = angular.module('ngModalDemo', ['ui.bootstrap'])
.controller('formController', function($scope, $modal, $log){
$scope.openModal = function () {
var modalInstance = $modal.open({
templateUrl: 'SomeModal.html',
controller: [
'$scope', '$modalInstance', function($scope, $modalInstance){
$scope.closeModal = function () {
$modalInstance.close();
};
}
]
});
};
})
})();

I was struggling with the same problem and the best thing I came up with was to use anonymous function as a modal controller. In that way all the logic is in the same controller and you don't have to create separate controller for each modal window.
This would look like this:
(function(){
var app = angular.module('ngModalDemo', ['ui.bootstrap'])
.controller('formController', function($scope, $modal){
$scope.openModal = function () {
var modalInstance = $modal.open({
templateUrl: 'SomeModal.html',
controller: [
'$scope', '$modalInstance', 'data', function($scope, $modalInstance, data) {
$scope.data = data;
$scope.ok = function() {
$modalInstance.close();
};
$scope.closeModal = function() {
$modalInstance.dismiss();
};
}
]
});
};
})
})();
PS. Haven't tested code above, just put it together from your provided code and fragments from one of my projects.

You can also try this
var modalInstance = $modal.open({
templateUrl : 'someTemplate.html',
scope : $scope,
size : 'md'
});

Related

Bootstrap modal popup open and close using angularjs not working

Hi i want to open and close the bootstrap model popup by using angularjs controller.js code.
my controller code
app.controller('RoleViewCtrlq', ['$scope', '$modalInstance', '$modal',
function ($scope, $modalInstance, $modal) {
$scope.open = function () {
debugger;
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
});
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}
}
]);
Here i have create the sample
https://plnkr.co/edit/xRhCR7qidlr24M8nAOA6?p=preview
it is not working to open and close my pop up in controller.js code. can any one check the issue.??
<script type="text/ng-template" id="myModalContent.html">
Remove this script tag from HTML and try again. It is working
In the Plunker you have provided, you have not set any myModalContent.html.
When using:
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html'
});
Angular will check for a myModalContent.html file to include in the modal. It means creating the modal from a template.
After reviewing your code, I think this is not exactly what you are trying to achieve:
Forked your Plunker

$uibModalInstance is not defined

I am working bootstrap modal directive . I need to open modal popup on ajax error method and popup is showing fine. but on button click inside modal , Where i need to dismiss modal , I am getting error
$uibModalInstance is not defined
First on module , I have registered correctly
var angularFormsApp = angular.module("angularFormsApp", ["ngRoute", "ui.bootstrap"]);
then on angular controller , I have injected this directive correctly.
var loginController = function ($scope, $window, $routeParams, $uibModal, DataService)
then I am calling this modal by following code inside same controller
var onError = function (reason) {
$scope.modalOptions.headerText = "Error";
$scope.modalOptions.bodyText = reason.statusText;
$uibModal.open({
templateUrl: baseurl + 'app/ErrorMessages/PopUpErrorMessage.html',
controller: 'loginController',
scope: $scope
});
};
$scope.cancelForm = function () {
$uibModalInstance.dismiss();
};
Now as you can see I have created separate html file for modal and below is html
<div class="modal-header">
<h3>{{modalOptions.headerText}}</h3>
</div>
<div class="modal-body">
<p>{{modalOptions.bodyText}}</p>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-default" value="Close"
ng-click="cancelForm()" />
</div>
Now When I click close button I am getting error
ReferenceError: $uibModalInstance is not defined
at Scope.$scope.cancelForm (loginController.js:44)
Now I have gone though some different solution for same problem
Eg : http://plnkr.co/edit/6djuhA8ohMkrWW7zohg1?p=preview
But in this case above example is using two different controller but in my case I am using same controller ,and If i inject both $uibModal as well as $uibModalInstance then its not working
Yes uibModalInstance will be undefined.
You need to store the reference of your uibmodel and call close on that reference.
Like this :
var myModel = $uibModal.open({
templateUrl: baseurl + 'app/ErrorMessages/PopUpErrorMessage.html',
controller: 'loginController',
scope: $scope
});
and in close function:
$scope.cancelForm = function () {
myModel.close();
};
You need to injected $uibModalInstance in your Controller as follows
var loginController = function ($scope, $window, $routeParams, $uibModal, DataService,$uibModalInstance)
In your Controller from where you are opening modal, you need to inject the dependency $uibModal.
To open the modal you need to specify a html template, controller for the modal.
$scope.ErrorModal = function(index) {
var modalInstance = $uibModal.open({
animation: true,
backdrop: 'static',
templateUrl: "/PopUpErrorMessage.html",
controller: "popupErrorMsgController",
controllerAs: "PEMCtrl",
size: "md",
resolve: {
modalInstanceData: {
headerText: "Error",
bodyText:reason.statusText
}
}
});
modalInstance.result.then(function(receivedObject) {
//Modal closed
});
Now in your Modal Controller -popupErrorMsgController you can access the modal instance by injecting $uibModalInstance. Also you can inject the other parameters which you want to resolve in your modal controller
angular.module('yourApp')
.controller('popupErrorMsgController', popupErrorMsgController);.
popupErrorMsgController.$inject = ['$scope', '$uibModalInstance', 'modalInstanceData'];
function popupErrorMsgController($scope, $uibModalInstance, modalInstanceData) {
$scope.modalInstanceData = modalInstanceData;
$scope.cancelForm = function(){
var objectToSend = {};
$uibModalInstance.close(objectToSend);
}
}
In your modal controller you can assign the received parameters to the $scope of modal and access it inside your modal HTML template.
<h3>{{modalInstanceData.headerText}}</h3>
Hope this works for you!

Passing data between modal and controller

How can I make data available in a controller? I have created a really simple Plunk that should show data on the $scope in a modal. I’ll then need to update the data, and only update $scope on clicking “ok”. Clicking “cancel” will discard the changes.
But before I get to that step, I need to make the scope available to the modal. Most of the examples use two controllers. Do I need another controller as in this example: Passing Data to Twitter Bootstrap Modal in Angular? In my controller I have the following:
$scope.open = function(){
var modalInstance = $uibModal.open({
templateUrl: 'modal.html',
controller: 'ModalInstanceController',
resolve: {
users: function() {
return $scope.users;
}
}
});
};
How can I display the users in the template? The plunk is here: http://plnkr.co/edit/FuXjSwtljQtFYOtFRV18?p=preview
To be able to access scope of the controller you need to pass scope object to the modal when creating an instance of it:
$scope.open = function() {
var modalinstance = $uibModal.open({
scope: $scope,
templateUrl: 'modal.html',
resolve: {
users: function() {
return $scope.users;
}
}
})
};
This way Angular will create child scope of the controller $scope so you will be able to access items inside of modals scope:
Demo: http://plnkr.co/edit/0m9oktX2JHFmeiaDfOpO?p=preview
You can access scope in modal -
$scope.open = function(){
var modalinstance = $uibModal.open({
templateUrl: 'modal.html',
scope:$scope
})
};
you can do it with just one controller, is just that is a "dirty" solution, because both html files will share the same controller, which is potentially an issue.
the problem you are facing is that in the modal you don't have a defined scope, so the foreach (ng-repeat) you are doing is not getting any elements
you can fix it easily by changing your modal.html to
<div ng-controller="modalController"><div class="modal-header">
<h3 class="modal-title">Modal</h3>
</div>
<div class="modal-body">
<p>Existing users:</p>
<ul>
<li ng-repeat="user in users">{{user}}</li>
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-default" type="button">Close</button>
</div>
</div>
as you see, now this modal has a controller (the same as the main window) and so will have a scope
or else just pass the scope to the modal definition adding
var modalinstance = $uibModal.open({
scope: $scope,...
is dirty, and you are "polluting" the scope, but it works :)
Here is some code from my current project it works as expected if you want to use any ng-click on the modal your function has to reside in ModalInstanceController
app.controller('dashboardCtrl', function ($scope, $rootScope, $location, $http, Data, $uibModal ) {
$scope.users = '';
$scope.open = function(){
var modalInstance = $uibModal.open({
templateUrl: 'modal.html',
controller: 'ModalInstanceController',
resolve: {
users: function() {
return $scope.users;
}
}
})
}
});
app.controller('ModalInstanceController', function ($scope, $uibModal, $uibModalInstance, users, $rootScope, $http, Data) {
$scope.ok = function () {
$uibModalInstance.close($scope.selected.item);
}
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
}
$scope.users = users ;
$scope.selected = {
users: $scope.users[0]
};
});

Unknown provider: $modalInstanceProvider <- $modalInstance in Angularjs modal

I am using angular bootstrap ui modal which is working fine but when I try to close it using modalInstance it gives above error.Here is my code
var app = angular.module('LoginModule', ['ui.bootstrap']);
app.controller('LoginModal', ['$scope', '$modal', function ($scope, $modal) {
$scope.animationsEnabled = true;
$scope.open = function (size) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/app/template/Login.html',
controller: 'LoginController',
size: size
});
}
}]);
app.controller('LoginController', ['$scope', '$modalInstance', '$http', function ($scope, $modalInstance, $http) {
$scope.model = {};
$scope.loading = {
state: false
}
$scope.errors = '';
$scope.email = "";
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]);
I have created the cancel function in the controller which I specify with the template still it gives error.I use ng-click="cancel()" in button inside LoginController .
Need help?
Looks like you are instantiating the controller with ng-controller directive in the modal view. Instead you only need to use controller option of the modal in order to get the special dependency $modalInstance injected. If you have instantiated controller using ng-controller="LoginController" you need to remove it and you would not need it as well as the controller would automatically be instantiated (by resolving special dependency $modalInstance) and attached to the template.

Angular UI $modal error

I have downloaded some of the angular UI directives, as i do not need them all. I have downloaded the latest file for modal from http://angular-ui.github.io/bootstrap/ and using this code
App.controller('PagesController', ['$scope', '$modal', 'PageFactory', function ($scope, $modal, PageFactory) {
$scope.pages = [];
PageFactory.getPages().then(function (pages) {
$scope.pages = pages;
}, function (err) {
console.log(err.message);
});
$scope.deletePage = function (page) {
var modalInstance = $modal.open({
templateUrl: 'pages-delete-modal.html',
controller: ['$scope', '$modalInstance', function ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]
});
modalInstance.result.then(function () {
// ok selected
}, function () {
});
};
}]);
Here is the template
<script type="text/ng-template" id="pages-delete-modal.html">
<div class="modal-header">
<h3 class="modal-title">Delete Confirmation</h3>
</div>
<div class="modal-body">
Are you sure you want to delete this page?
</div>
<div class="modal-footer">
<button class="btn btn-danger" ng-click="ok()">Delete</button>
<button class="btn btn-default" ng-click="cancel()">Cancel</button>
</div>
</script>
Now i seem to get an error saying
http://errors.angularjs.org/1.2.23/$injector/unpr?p0=%24modalProvider%20%3C-%20%24modal
I already have 'ui.bootstrap' injected into my app.js file here as you can see
var App = angular.module('MyApp', ['ui.router', 'ui.bootstrap']);
If i however use this link, instead of using the downloaded modal file, it works?
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.2.js"></script>
I have also downloaded the transition directive as i believe the modal directive is dependant on this, but i cannot see that i am missing anything else.
I am using the tpl.min.js files for both transition and modal.
Any help much appreciated
You should try change the modalInstance controller to a string with the name of an actual controller in your project.
$scope.deletePage = function (page) {
var modalInstance = $modal.open({
templateUrl: 'pages-delete-modal.html',
controller: 'otherCtrl'
});
modalInstance.result.then(function () {
// ok selected
}, function () {
});
};
and then create the controller itself
App.controller('otherCtrl',['$scope','$modalInstance', function($scope,$modalInstance){
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]);

Resources