When I click the cancel button on my modal, the $modalInstance.dismiss function binded with ng-click on my modal template isn't working.
The console has been throwing the error: "$modalInstance.dismiss is not a function"
MODAL TEMPLATE:
<div class="my-modal ng-scope" id="my-modal">
<div class="modal-header">
<h3 class="modal-title" id="modal-title">Create a new room</h3>
</div>
<div class="modal-body" id="modal-body">
<form>
Enter a room name<br>
<input type="text" name="new-room-name">
</form>
<div class="modal-footer">
<button class="btn btn-warning" type="button" ng-click="modal.cancel()">Cancel</button>
<button class="btn btn-primary" type="button" ng-click="modal.save()">Create Room</button>
</div>
</div>
MAIN CONTROLLER:
(function() {
function HomeCtrl(Room, $scope, $uibModal, $log, $document) {
var home = this;
home.chatRooms = Room.all;
//TO TEST ADD METHOD FROM ROOM.JS
// this.addRoom = Room.add();
home.open = function () {
modalInstance = $uibModal.open({
animation: true,
backdrop: true,
templateUrl: '../templates/modal.html',
controller: 'ModalInstanceCtrl',
controllerAs: 'modal',
bindToContoller: true,
scope: $scope,
size: 'lg',
resolve: {
'$modalInstance': function () { return function () { return modalInstance; } }
}
});
console.log(modalInstance);
modalInstance.result.then(function (newChatRoom) {
home.selected = newChatRoom;
console.log(newChatRoom);
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
}
angular
.module('blocChat')
controller('HomeCtrl', ['Room', '$scope', '$uibModal', '$log', '$document', HomeCtrl]);
})();
MODAL CONTROLLER:
(function() {
function ModalInstanceCtrl(Room, $scope, $modalInstance, $log, $document) {
var modal = this;
this.save = function() {
$modalInstance.close(newChatRoom);
};
this.cancel = function() {
$modalInstance.dismiss('cancel');
};
}
angular
.module('blocChat')
.controller('ModalInstanceCtrl', ['Room', '$scope', '$modalInstance', '$log', '$document', ModalInstanceCtrl]);
})();
I've spent about 3 hours messing around with my code, looking at the AngularJS Bootstrap UI documentation, several StackOverflow threads, and other sites and have gotten no where. Any help would be appreciated.
In the version of angular ui bootstrap you're using, the reference to the modal instance is called $uibModalInstance. So try changing your controller to this:
(function() {
function ModalInstanceCtrl(Room, $scope, $uibModalInstance, $log, $document)
{
var modal = this;
this.save = function() {
$uibModalInstance.close(newChatRoom);
};
this.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
}
angular
.module('blocChat')
.controller('ModalInstanceCtrl', ['Room', '$scope', '$uibModalInstance', '$log', '$document', ModalInstanceCtrl]);
})();
Related
I am new to Angular. I have created a component with a template (panel.html) and a controller (allPanelsRetrieved). When a specific button defined in the template is clicked, the showDetails() function specified in the controller is called. This function triggers the opening of a modal dialog specified by a template (panel-list.details-template.html) and a controller, which are both defined inside the allPanelsRetrieved controller. The problem is that the modal dialog is displayed but the controller doesn't work (the click of the OK button does nothing). Where the problem may be? Thanks in advance
angular.
module('panelList')
.component('panelList', {
templateUrl: '/panel-list/panel.html',
controller: ['Panel', 'NgTableParams','$scope', '$location', '$uibModal',
function PanelListController(Panel, NgTableParams, $scope, $location, $uibModal) {
this.allPanelsRetrieved = (index, before) => {
//..hidden code here
}
this.showDetails = function () {
$uibModal.open({
templateUrl: '/panel-list/panel-list.details-template.html',
controller: function ($uibModalInstance) {
let $ctrl = this;
$ctrl.ok = function () {
$uibModalInstance.close();
};
},
}).result.then(
function (success) {
alert(success);
},
function (error) {
alert(error);
}
);
};
}]
});
Here is the template panel-list.details-template.html:
<div>
<script type="text/ng-template" id="/panel-list/panel-list.details-template.html">
<div class="modal-header">
<h3 class="modal-title">Modal title</h3>
</div>
<div class="modal-body">
Modal content
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="$ctrl.ok()">Close</button>
</div>
</script>
Use $scope to make it work in the AngularJS way. Here is a working plnkr demo of what you try to achieve.
$uibModal.open({
templateUrl: '/panel-list/panel-list.details-template.html',
controller: function ($uibModalInstance, $scope) {
$scope.ok = function () {
$uibModalInstance.close();
};
}
}).result.then(
function (success) {
alert(success);
},
function (error) {
alert(error);
}
);
View
<script type="text/ng-template" id="/panel-list/panel-list.details-template.html">
<div class="modal-header">
<h3 class="modal-title">Modal title</h3>
</div>
<div class="modal-body">
Modal content
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">Close</button>
</div>
</script>
While the angular.component implementation provides a default for the controllerAs syntax...
controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',
...it appears that angular-ui-bootstrap does not.
Simply provide a value for controllerAs in your $uibModal options to continue using the preferred syntax.
$uibModal.open({
templateUrl: '/panel-list/panel-list.details-template.html',
controllerAs: '$ctrl',
controller: function($uibModalInstance) {
let $ctrl = this;
$ctrl.ok = function () {
$uibModalInstance.close();
}
}
http://plnkr.co/edit/q1arN18553XoUZEuPcPl?p=preview
The problem is with this keyword as you are using it. Use arrow function instead and it will work:
$uibModal.open({
templateUrl: '/panel-list/panel-list.details-template.html',
controller: ($uibModalInstance) => {
let $ctrl = this;
$ctrl.ok = function () {
$uibModalInstance.close();
};
},
})
I would like to use the ui-bootsrap Modal with the AngularJS Fullstack Generator & ES6, but it doesn't work.
I would like to choose a Project, click "Edit" and edit the Project in a large Modal. But I don't get the modal to open.
In the Console, I get this error Message:
"Error: $modal is not defined"
My Project Controller looks like this:
'use strict';
(function() {
class ProjectCtrl {
constructor(Project, $modal, $log) {
this.project = Project;
this.projects = [];
this.getAllProjects(Project);
this.$modal = $modal;
this.log = $log;
}
// Open a modal window to Update a single Project
modalUpdate(size, selectedProject) {
var modalInstance = $modal.open({
templateUrl: 'app/project/project-edit.modal.html',
controller: function ($scope, modalInstance, aProject) {
$scope.project = aProject;
},
size: size,
resolve: {
aProject: function () {
return selectedProject;
}
}
});
modalInstance.result.then(function (selectedItem) {
this.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
}
angular.module('projectApp')
.controller('ProjectCtrl', ProjectCtrl);
})();
app.js looks like this:
'use strict';
angular.module('projectApp', [
'projectApp.constants',
'ngCookies',
'ngResource',
'ngSanitize',
'ui.router',
'ui.bootstrap'
])
.config(function($urlRouterProvider, $locationProvider) {
$urlRouterProvider
.otherwise('/');
$locationProvider.html5Mode(true);
});
The Button to open the Modal:
<button type="button" class="btn btn-default btn-xs pull-right" ng-click="ProjectCtrl.modalUpdate('lg', project)"><span aria-hidden="false"></span> Edit</button>
My guess is that in ProjectCtrl, I have somehow to $inject 'Project', '$modal' & '$log', but I don't know how and where.
I solved the Modal problem in another way, cause it seems that UI Bootstrap doesn't work in ES6. At least not now.
I used the Modal Service here for Angular-Fullstack.
Here is a simple example with a delete Modal:
'use strict';
(function() {
class AdminController {
constructor(User, Modal) {
// Use the User $resource to fetch all users
this.users = User.query();
this.modal = Modal;
}
delete(user) {
var deleteConfirmationModal = this.modal.confirm.delete((user) => {
user.$remove();
this.users.splice(this.users.indexOf(user), 1);
});
deleteConfirmationModal(user.name, user);
}
}
angular.module('sampleApp.admin')
.controller('AdminController', AdminController);
})();
This is how the Modal looks like:
Which version of ui-bootstrap are you using ?
The syntax is different depending on which version you're using.
Assuming you're using v0.13.4 or older and without ES6, here the solution :
NOTE :
If you're using more recent version than v0.13.4 then replace $modal by $uibModal and $modalInstance by $uibModalInstance and it should work too.
First, what you need to do is write in the command line :
yo angular-fullstack:controller MyModalName
then in myModalName.controller.js put this :
.controller('MyModalNameCtrl', function ($scope,$modal) {
$scope.openModal = function () {
var modalInstance = $modal.open({
animation: true,
templateUrl: 'testmodal',
controller: 'ModalInstanceCtrl',
});
modalInstance.result.then(function () {}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
});
Then still in myModalName.controller.js put below :
//change theNameOfYourApp to your corresponding app name !
angular.module('theNameOfYourApp').controller('ModalInstanceCtrl', function ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
Then last step, in your .html page where you want to display the modal, put :
<!--Modal Template-->
<div ng-controller="MyModalNameCtrl">
<script type="text/ng-template" id="testmodal">
<div class="modal-header">
<h3 class="modal-title">Hello :</h3>
</div>
<div class="modal-body">
<p>hey, this is the body </p>
</div>
<div class="modal-footer">
<button class="btn btn-default" type="button" ng-click="ok()">OK</button>
<button class="btn btn-default" type="button" ng-click="cancel()">Cancel()</button>
</div>
</script>
</div>
var app = angular.module('jkuri.gallery', []);
app.controller("userProfile", ['$scope', '$http', '$location', '$resource', 'fullname', '$timeout', function($scope, $http, $location, $resource, fullname, $timeout){
$scope.openAlbum = function(){
$scope.showInject2 = true;
};
$scope.closeAlbum = function(){
$scope.showInject2 = false;
console.log("hover");
};
$scope.dataUri = function(){
//console.log('Res image', $scope.resImageDataURI);
//console.log($scope.resBlob);
console.log($scope.urlBlob);
//$scope.file = new File($scope.urlBlob, "name");
//console.log($scope.file);
$scope.loading = true;
$scope.cropOne = false;
$scope.sendRequest($scope.urlBlob, $scope.id, $scope.description, $scope.photoTag);
}
}]);
app.directive('ngGallery', ['$document', '$timeout', '$q', '$templateCache', '$location',function($document, $timeout, $q, $templateCache, $location) {
'use strict';
return {
restrict: 'EA',
scope: {
images: '=',
thumbsNum: '#',
sendRequest: '='
},
templateUrl: function(element, attrs) {
return attrs.templateUrl || defaults.templateUrl;
},
link: function (scope, element, attrs) {
setScopeValues(scope, attrs);
scope.images = [
{"id":"84","img":"images/image2.jpg","thumb":"images/image2.jpg"},
{"id":"85","img":"images/image2.jpg","thumb":"images/image2.jpg"},
{"id":"86","img":"images/image2.jpg","thumb":"images/image2.jpg"},
{"id":"87","img":"images/image2.jpg","thumb":"images/image2.jpg"},
{"id":"89","img":"images/image2.jpg","thumb":"images/image2.jpg"}
];
scope.sendRequest = function(imgBlob, id, imgDescription, imgTag){
console.log(imgBlob);
console.log(id);
console.log(imgDescription);
console.log(imgTag);
//scope.images.push({"id":id,"img":imgBlob,"thumb":imgBlob, "description":imgDescription});
scope.images.push({"id":"89","img":"images/image3.jpg","thumb":"images/image3.jpg"});
$timeout(function() {
var calculatedWidth = calculateThumbsWidth();
$thumbnails.css({ width: calculatedWidth.width + 'px' });
},100);
};
}
};
}]);
<div ng-app="jkuri.gallery" ng-controller="userProfile" class="cropppe">
<!-- <div class="cropped-one"><img ng-src="{{resImageDataURI}}" /></div> -->
<div class="cropped-one"><img ng-src="{{urlBlob}}"/></div>
<div class="float-right-btns">
<textarea name="" rows="" cols="" placeholder="Give a description"></textarea>
<a onclick='show();'>Cancel</a>
<a class="mfp-close" ng-click="dataUri()" style="background:#448ccb;color:#fff;">Upload</a>
</div>
</div>
<div ng-if="showInject2" style="position:absolute;" ng-gallery images="images" thumbs-num="11" send-request="sendRequest">
</div>
<div class="ng-gallery">
<div class="ng-scope">
<img class="ng-thumb" src="image1.jpg" ng-click="openAlbum()" ng-mouseover="closeAlbum()">
<div class="link-album"><p><strong>View</strong> or <strong>Add/Change</strong><br>Pictures</p></div>
</div>
I have a page in which directive is called when ng-if is true normally directive function is calling when i put directive in the page...and when ng-if gets true...after that function from controller is not calling function which is inside directive.
Exactly problem i am facing is that sendRequest function isn't calling from controller of directive and if i put that directive without ng-if it works like a charm...
Error: $scope.sendRequest is not a function
I have just simply added $parent in the function
<div ng-if="showInject2" style="position:absolute;" ng-gallery images="images" thumbs-num="11" send-request="$parent.sendRequest">
I created a Modal service and when I injected the service into the controller, I am receiving an error that says "$Injector: unpr Unknown Provider". Here is my code below. Let me know if I am missing something.
This is the service I have so far.
'use strict';
angular.module('myApp.services', [])
.factory('modalService', ['$scope', function($scope) {
return {
openMenuModal: function(templateLink, windowAnimation) {
var modalInstance = $modal.open({
templateUrl: templateLink,
backdrop: 'static',
windowClass: windowAnimation,
controller: function($scope, $modalInstance) {
$scope.close = function() {
$modalInstance.close();
};
},
size: 'md',
scope: $scope,
keyboard: true
});
}
};
}]);
Here is the controller I have set up.
angular.module('myApp.controllers', ['ui.bootstrap', 'ngAnimate'])
.controller('HomeCtrl', function($scope, $http, $modal, modalService) {
$scope.opentheBook = modalService.openMenuModal('partials/Books.html', 'animated zoomIn');
});
Here is the template for the data in the modal - Books.html
<div ng-controller="HomeCtrl">
<div class="modalBox animated fadeIn">
<button class="btn btn-danger pull-right" type="button" ng-click="" tooltip="Close"><i class="fa fa-times"></i></button>
<h1>title</h1>
<p>description</p>
<div class="next">
<button class="btn btn-danger pull-right" type="button" tooltip="Close"><i class="fa fa-times"></i></button>
</div>
</div>
</div>
Here is the main home page where I am calling the openBook() to open the modal with the info from the json
<div class="Books">
<ul>
<li ng-repeat="book in thing.Books" class="list-unstyled"><a ng-click="opentheBook" href="#"><h6>{{book.name}}</h6></a></li>
</ul>
</div>
json for Books example --inside another array called things
"Books": [
{
"name": "Name of Book 1",
"description": "Description about book..."
},
{
"name": "Name of Book 2",
"description": "Description about book..."
}
]
This error results from the $injector being unable to resolve a required dependency. To fix this, make sure the dependency is defined and spelled correctly. For example, the following code will fail with the same error you received -$injector:unpr, if myService is not defined:
angular.module('myApp', [])
.controller('MyController', ['myService', function (myService) {
// Do something with myService
}]);
Making sure each dependency is defined will fix the problem, as noted below.
angular.module('myApp', [])
.service('myService', function () { /* ... */ })
.controller('MyController', ['myService', function (myService) {
// Do something with myService
}]);
So to answer your question, in your case you appear to be missing dependency
angular.module('myApp.controllers', ['ui.bootstrap', 'ngAnimate'])
.controller('HomeCtrl', function($scope, $http, $modal, modalService) {
$scope.opentheBook = modalService.openMenuModal('partials/Books.html', 'animated zoomIn');
});
To Inject modalService like so:
.controller('HomeCtrl', ['modalService', function($scope, $http, $modal, modalService) {
}]);
You also need to change up your factory module to angular.module('myApp.services', ['ui.bootstrap']) and use $uibModal since $modal is deprecated.
angular.module('myApp', ['ui.bootstrap'])
.factory('modalService', ['$uibModal', function($uibModal) {
return {
openMenuModal: function(templateLink, windowAnimation) {
var modalObj = $uibModal.open({
templateUrl: templateLink,
backdrop: 'static',
windowClass: windowAnimation,
controller: function($scope,$modalInstance){
$scope.ok = function(id){
//Process OK Button Click
$modalInstance.close();
},
$scope.cancel = function(){
$modalInstance.dismiss('cancel');
}
},
size: 'md',
keyboard: true,
resolve: {
someData: function () {
return 'Return some Data';
}
}
});
}
};
}])
.controller('HomeCtrl', ['$scope','modalService', function($scope, modalService, someData) {
$scope.dataFromService = someData;
$scope.opentheBook = function(){
modalService.openMenuModal('myModalContent.html', 'animated zoomIn');
};
}]);
UPDATE 1
As mentioned in the comments, do not attempt to inject $scope to your factory. Here is a Plunker I created which lets you open a modal by calling the factory.
http://plnkr.co/edit/G68NVYZlTqrIS0N2TKL4
I'm creating a simple update modal. To do so, I'm passing a parameter into my angular-bootstrap modal. I've two controllers, ModalCtrl and ModalInstanceCtrl:
adminController.controller('ModalCtrl', ['$scope', '$modal', '$log', 'Profile',
function ($scope, $modal, $log, Profile) {
$scope.open = function (profile) {
var modalInstance = $modal.open({
animation: true,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
resolve: {
profile: function () {
$log.info(profile);
return profile;
}
}
});
modalInstance.result.then(function (updatedProfile) {
$log.info(updatedProfile);
Profile.post(updatedProfile);
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
}]);
adminController.controller('ModalInstanceCtrl', function ($scope, $modalInstance, profile) {
$scope.ok = function () {
$modalInstance.close(profile);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
The profile is logged both when opening and accepting the modal - leading me to believe that it's being passed into the instance without issue. However, displaying the modal doesn't display anything from that profile object:
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Profile View</h3>
</div>
<div class="modal-body">
<div><p>{{profile.profileType}}</p></div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
<button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
</div>
</script>
What am I doing wrong?
You need to put the profile object on the $scope for it to be accessible in the HTML template:
adminController.controller('ModalInstanceCtrl', function ($scope, $modalInstance, profile) {
$scope.profile = profile;
$scope.ok = function () {
$modalInstance.close(profile);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});