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
});
}
Related
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]
};
});
I am trying to populate a modal form with data passed in from my controller. The data being displayed is always NULL, even though I have populated the data in the controller.
I have been trying to work this out and have tried a few different ways to do it but none work.
The examples I have seen use $scope, but I don't want to use $scope and instead use controller as
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
(function () {
'use strict';
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function($uibModal, $log) {
var vm = this;
vm.vehicle = [{
vehicleRegistration: null,
createUser: null
}];
vm.open = function (size) {
vm.vehicle[0]["vehicleRegistration"] = 'ABCDEFG';
vm.vehicle[0]["createUser"] = 'BOBF';
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: 'lg',
resolve: {
items: function () {
return vm.vehicle;
}
}
});
};
});
})();
(function () {
'use strict';
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($uibModalInstance, items) {
var vm = this;
// I want to get the vehicle data pass to populate the form myModalContent.html
vm.vehicle = items;
});
})();
Any ideas?
Here is http://plnkr.co/edit/grHKGEJeKqoR8VHOW8I6?p=preview
First, use another name than vm for the modal. I've set it to vm2, also when defining the modal, you have to set the alias for the controller using the word as like this:
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl as vm2',
size: 'lg',
resolve: {
items: function () {
return vm.vehicle;
}
}
});
Check the link: http://plnkr.co/edit/JmCL6NjAmd2b1UPR8649
I have set up a plunkr here:
http://plnkr.co/edit/NdHqQJ?p=preview
I'm trying to push and pull the form data into the modal window when you click on the task. I have read that you can do this with the "resolve" property (seen below) of the modal but I have been unable to get it to actually work. Any insight would be greatly appreciated.
var modalInstance = $modal.open({
templateUrl: 'editTask.html',
controller: 'ModalInstanceCtrl',
size: size,
scope: $scope,
resolve: {
items: function () {
return $scope.items;
}
}
});
Please let me know if you need more details!
If you want to use resolve (you can) the nit will be like this for example:
$scope.open = function(size, task) {
var modalInstance = $modal.open({
templateUrl: 'editTask.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
task: function() {
return task
}
}
});
};
HTML:
<a ng-click="open('lg', noStoneTask)" style="cursor:pointer" tooltip-placement="top" tooltip="Open Task">{{noStoneTask.taskSubject}}</a>
Demo: http://plnkr.co/edit/NA71479d04Yw7hh2Twx8?p=preview
You have to pass the scope you want to resolve (pass to the modal) in the resolve. and resolve it in the modal controller.
Is this what you want to achieve?
http://plnkr.co/edit/Q0G79C?p=preview
I modified the modal to pass the noStoneTasks scope to the modal
//modal
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: 'editTask.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
noStoneTasks: function () {
return $scope.noStoneTasks;
}
}
});
};
I also modify the scope when the user click ok.
uxModule.controller('ModalInstanceCtrl', function ($scope, $modalInstance, noStoneTasks) {
$scope.ok = function () {
noStoneTasks[0].actHours++;
$modalInstance.close('save');
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
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.
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'
});