I'm trying to implement an AngularJS Modal.
This is my call for the modal
<button data-ng-disabled="!caixa.ativo" data-ng-click="abrir(caixa.id)" class="btn btn-primary btn-xs">Alterar</button>
This is my function
$scope.abrir = function(caixaId) {
var modalInstance = $modal.open({
templateUrl: 'add_modal',
controller: $scope.model,
resolve: {
id: function() {
return caixaId;
}
}
});
};
$scope.model = function($scope, $modalInstance) {
$scope.alerts = [];
//if I remove this code, the modal opens correctly
if (angular.isDefined(id))
alert('edit');
};
But when I click the button, I get this error
Error: id is not defined
$scope.model#http://localhost:8080/websys/resources/js/CaixaController.js:38:1
invoke#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.js:4182:14
instantiate#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.js:4190:27
$ControllerProvider/this.$get</<#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.js:8449:18
resolveSuccess#http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js:1710:32
processQueue#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.js:13170:27
scheduleProcessQueue/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.js:13186:27
$RootScopeProvider/this.$get</Scope.prototype.$eval#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.js:14383:16
$RootScopeProvider/this.$get</Scope.prototype.$digest#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.js:14199:15
$RootScopeProvider/this.$get</Scope.prototype.$apply#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.js:14488:13
ngEventHandler/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.js:22954:17
m.event.dispatch#http://code.jquery.com/jquery-latest.min.js:3:8384
m.event.add/r.handle#http://code.jquery.com/jquery-latest.min.js:3:5122
The reason your ID is not defined is you are not injecting id as a dependency to your controller.
$scope.abrir = function(caixaId) {
var modalInstance = $modal.open({
templateUrl: 'add_modal',
controller: modalController,
resolve: {
// adding id as a property here allows you to inject it
// into the controller defined below
id: function() {
return caixaId;
}
}
});
};
// you don't need to bind this controller to your scope
// you don't need to inject $modalInstance as a dependency here,
// but you do need to inject id
function modalController($scope, id) {
$scope.alerts = [];
// now id should be defined since you added it as a dependency
if (angular.isDefined(id))
alert('edit');
};
Related
In my angular project I'm using Angular.js material. And I want to show $mdialog with custom controller, where user changes some data and this data should be applied to my $scope variable. Example what I do now:
function myControllerFn($scope, MyService){
// I do copy of my service variable because I don't want to change it until user will click save button
$scope.name = angular.copy(MyService.name);
$scope.editCurrentProfile = function() {
$scope.showEditProfileDialog($scope.name).then(function(name){
$scope.name = name;
}
}
$scope.showEditProfileDialog = function(name) {
var deferred = $q.defer();
$mdDialog.show({
controller: 'editProfileViewCtrl',
templateUrl: 'controllers/editProfileDialog.tmpl.html',
locals: {
name: name,
deferred: deferred
}
});
return deferred.promise;
};
}
Then in dialog controller I do:
function editProfileViewCtrl($scope, name, deffered) {
deferred.resolve('newName');
}
But I think it is the wrong way. So what is the best way to communicate between two view controllers in angular without new service ? Or better create another service like: EditDialogService, where I will save results ?
When you open a modal, the show() function returns a promise.
$scope.showEditProfileDialog = function(name) {
var modalInstance = $mdDialog.show({
controller: 'editProfileViewCtrl',
templateUrl: 'controllers/editProfileDialog.tmpl.html',
locals: {
name: name
}
});
modalInstance.then(function(result){
// acces what is returned
// In your case, you would do
$scope.name = result;
}, function(error){
// Usually when you cancel your modal
});
}
Your modal controller can be injected with $mdDialog.
function editProfileViewCtrl($scope, name, $mdDialog) {
$scope.close = function() {
$mdDialog.hide('newName');
}
}
You should create a directive with your user as scope variable. Angular in itself is handling the data binding.
It is possible to create a minimal controller function that has access to $scope.
$mdDialog.show({
controller: function () { this.parent = $scope; },
templateUrl: 'controllers/editProfileDialog.tmpl.html',
locals: {
name: name,
deferred: deferred
}
});
Im using md-dialog from Material Design and I came across a small issue which causes me a lot of trouble.
I'm using this dialog as a form for creating a new record in db and I need its controller to be loaded from external file. The reason is that I'm using the same dialog in many places of the app (in many other controllers) and I dont want to copy and paste it to each one of them.
I've tried to write it as a service, but the problem is, as I'm binding data from form to the controller I'm using $scope and that way i got "$scope is not defined". When I add $scope as dependencies in that service, I'got injection error.
Do you have any ideas how to load modal controller externally so it will work even with using of $scope?
$scope.showNewContactDialog = function($event) {
var parentEl = angular.element(document.body);
$mdDialog.show({
parent: parentEl,
targetEvent: $event,
templateUrl: 'app/Pages/directory/contacts/newContact.dialog.html',
controller: NewCompanyContactDialogCtrl,
clickOutsideToClose: true,
hasBackdrop: true
});
};
// New User dialog controller
function NewCompanyContactDialogCtrl($scope, $mdDialog) {
var self = this;
$scope.modalIcon = "add";
$scope.modalTitle = 'Nová položka';
$scope.modalAdvanced = true;
// Country Selector
apiCalls.getData(countryUrl, function(response){
$scope.countries = response;
})
// Add New Object
$scope.newItem = function() {
var url = baseUrl + 'new/';
var data = JSON.stringify({
code: $scope.newItem.contactCode,
first_name: $scope.newItem.contactFirstName,
last_name: $scope.newItem.contactLastName,
street: $scope.newItem.contactStreet,
city: $scope.newItem.contactCity,
country: $scope.newItem.contactCountry,
postal: $scope.newItem.contactPostal,
pobox: $scope.newItem.contactPobox,
price_lvl: $scope.newItem.contactPriceLvl,
orgid: $cookies.get('orgid')
});
apiCalls.postData(url, data, function(response){
console.log(response);
// Toast
if(response.status == 201){
$mdToast.show(
$mdToast.simple()
.textContent('Záznam bol vytvorený.')
.position('bottom right')
.action('Skryť')
.highlightAction(true)
.highlightClass('md-warn')
);
$mdDialog.cancel();
}
});
}
To use as service you can do something like:
angular.module('myApp').factory('newCompModal', function($mdDialog){
var parentEl = angular.element(document.body);
function show($event){
return $mdDialog.show({
parent: parentEl,
targetEvent: $event,
templateUrl: 'app/Pages/directory/contacts/newContact.dialog.html',
controller: 'NewCompanyContactDialogCtrl',
clickOutsideToClose: true,
hasBackdrop: true
});
}
return {
show: show
}
});
Then in any controller:
angular.module('myApp').controller('someController',function($scope,newCompModal){
$scope.newCompanyModalShow = newCompModal.show;
})
And pass event in from view
<button ng-click="newCompanyModalShow($event)">New Company</button>
If you need to pass data also from controller to modal you can add another argument and pass it to locals property of $mdDialog or share through another service property
Example of a dialog with external controller:
$mdDialog.show({
scope : scope,
preserveScope : true,
templateUrl : 'template/search.html',
targetEvent : event,
clickOutsideToClose : true,
fullscreen : true,
controller : 'DialogController'
});
And the controller search.js:
(function() {
angular.module('myApp')
.controller('DialogController', DialogController);
DialogController.$inject = ['$scope', '$mdDialog'];
function DialogController($scope, $mdDialog) {
$scope.closeOpenedDialog = closeOpenedDialog;
function closeOpenedDialog() {
$mdDialog.hide();
}
}
})();
If your mdDialog config doesn't recognize your controller name because it belongs to an external file, then instead of doing this:
controller : 'DialogController'
You should load your controller as a directive in your dialog's view:
<md-dialog ng-controller="DialogController">
...
</md-dialog>
I want to update some value of a $modal in AngularJS but unable to understand how I can do this. Sample code is below:
var modalInstance;
function setupCall(data) {
var templateURL = 'partials/Chat.html';
var cssClass = 'medium-Modal';
modalInstance = $modal.open({
backdrop: "static",
keyboard: false,
backdropClick: false,
windowClass: cssClass,
templateUrl: templateURL,
controller: function ($scope, $modalInstance) {
$scope.updateStatus=function() {
...
}
}
});
modalInstance.result.then(function() {
});
}
// first time i call this function to open model
setupCall(event);
Now when model open successfully and if I received some update from service and I again want to show updated values in a model then how I can call updateStatus() from outside the model. I try to using
modalInstance.updateStatus(..) but it is not working. Can someone tell me a proper way to do this?
You can pass a scope option to $modal, and then use AngularJS events
var modalScope = $rootScope.$new();
myService.doSomethingAsync(function (data) {
$rootScope.$emit('some event', data);
});
$modal.open({
scope: modalScope,
controller: function ($scope) {
/* ... */
$scope.$on('some event', function() {
$scope.updateStatus();
});
}
});
You can use $broadcast to call that method. For example, after you received update from your service in your view's controller (where you are calling setupCall or launching the modal), do this:
$rootScope.$broadcast("dataUpdatedFoo", {newData: "bar"));
Now, inside your controller of modal, register a listener for this:
$scope.$on("dataUpdatedFoo", function(e, data) {
$scope.updateStatus();
});
Thanks everyone. I resolve this by adding custom eventlistener.
var listeners = [];
function _addEventListener(listener) {
listeners.push(listener);
return listener;
}
function _removeListener(listener) {
for (var i=0; i < listeners.length; i++){
if (listeners[i] === listener){
listeners.splice(i, 1);
break;
}
}
}
function setupCall(data) {
......
modalInstance = $modal.open({
backdrop: "static",
keyboard: false,
backdropClick: false,
windowClass: cssClass,
templateUrl: templateURL,
controller: function ($scope, $modalInstance) {
var listener = _addEventListener(function (event) {
$log.info("chat msg: "+JSON.stringify(event));
});
$scope.$on('destroy', function () {
_removeListener(listener)
});
...
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'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