Passing data between modal and controller - angularjs

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]
};
});

Related

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..

$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!

AngularJS passing data to bootstrap modal

I think I'm missing something but cannot figure what.
Basically I'm trying to pass an object to the modal like below, but instead of getting the passed object I gets null...so I think is a problem with the scope but I'm new in Angular and need some help.
Controller
app.controller("musicViewModel", function ($scope, $http, $location, $uibModal, $log) {
$scope.selected = null;
$scope.open = function (item) {
$scope.selected = item;
$log.info('Open' + $scope.selected); // get right passes object
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
controller: 'musicViewModel',
size: 'lg',
resolve: {
items: function () {
return $scope.selected;
}
}
});
};
$scope.toggleAnimation = function () {
$scope.animationsEnabled = !$scope.animationsEnabled;
};
});
View
<div class="row" ng-controller="musicViewModel">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<ul>
<li>
{{ selected }} // always gets null
</li>
</ul>
</div>
</script>
</div>
I'd suggest you to pass the scope of your own controller instead of passing same controller again, by doing that you can remove the resolve also.
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
scope: $scope, //passed current scope to the modal
size: 'lg'
});
Otherwise you need to create a new controller and assign that controller for modal while opening it.
When you use resolve, the map is injected into the given controller.
I recommend that u use a different controller to handle the modal functionality (separation of concerns).
I also recommend to use dependency injection to support minification of the code. Step 5 on the Angular tutorial wil explain this.
A simplified example of the modal controller would be.
(function () {
'use strict';
var app = angular.module('App');
app.controller('musicDetailController',
['$scope', '$uibModalInstance', 'items',
function ($scope, $uibModalInstance, items) {
$scope.items = items;
}]);
}());
You cannot pass an object directly.
I've tried all the solutions above, but wasn't really satisfied. I've solved the issue by writing a simple parser that enables you to pass both strings and objects directly to the modal, through the provided resolve function.
app.controller('ModalController', ['$uibModal', '$scope', function ($uibModal, $scope) {
// Initialize $modal
var $modal = this;
// Open component modal
$modal.open = function (component, size, data) {
// Init modal
var modalInstance = $uibModal.open({
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
component: component,
size: size || 'md',
resolve: parseResolve(data)
});
};
// Parse the resolve object
function parseResolve(data) {
if (typeof data === 'string') {
return {
data: function() {
return data;
}
}
}
else if (typeof data === 'object') {
var resolve = {};
angular.forEach(data, function(value, key) {
resolve[key] = function() {
return value;
}
})
return resolve;
}
}
}]);
When usings strings
Template:
<button ng-click="$modal.open('modalSomething', 'md', 'value'">
Click
</button>
Component:
bindings: {
resolve: '#'
}
When using objects
Template:
<button ng-click="$modal.open('modalSomething', 'md', {key1: value1, key2: value2})">
Click
</button>
Component:
bindings: {
resolve: '<'
}
I got the below code working:
this.OpenModal = function() {
var modalInstance = $uibModal.open({
url: "/name?parameter=" + $scope.Object.ParamValue,
templateUrl: 'views/module/page.html',
controller: myController
});
}

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

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'
});

Angular how to get access to $scope var from modal

I have a page where I have a button to launch a modal. Both pages has its own controllers. The question is how to get variable from page in modal controller?
You pass data to your modal controller using resolve.
var modalInstance = $modal.open({
templateUrl: 'template.html',
controller: 'MyModalCtrl',
resolve: {
variableToPass: function () {
return $scope.items;
}
}
});
Then you define your modal controller like this
myApp.controller('MyModalCtrl', ['$scope', $modalInstance'', 'variableToPass', function($scope, $modalInstance, variableToPass) {
...
}]);
Alternatively, or complementary, you can pass the whole $scope like this
var modalInstance = $modal.open({
templateUrl: 'template.html',
controller: 'MyModalCtrl',
scope: $scope
});

Resources