How to invoke a modal from a controller in angularjs / ui-bootstrap? - angularjs

I am trying to display a modal (Note view) from a controller (Details controller). I have separate controllers tied to each view.
The Details view has a list of radio buttons and upon selecting a radio button, it needs to display a modal with some data and OK and Cancel buttons.
Also, I need to deselect the radio button which is selected in Details view when cancel button is clicked on the modal.
How can I wire up all this? I am trying the below code and I get internal server error upon calling note modal from Details controller.
I copied some parts from my code to show what I am trying.
Thanks for any suggestions.
Details view:
<div class="list-group-item" ng-repeat="cpo in details.detailoptions">
<div class="row">
<h4><input type="radio" name="optRadio" ng-model="$parent.selectedOption"
ng-value="{{o}}" ng-change="optionSelected()"
ng-disabled="disableOptions" /></h4>
</div>
</div>
Details controller:
appControllers.controller('detailsCtrl', ['$scope', '$uibModal',
function ($scope, $uibModal) {
$scope.selectedOption;
$scope.optionSelected = function () {
//call note modal
$uibModal.open({
templateUrl: 'notePanel',
controller: 'noteCtrl',
scope: $scope
});
}
}
]);
Note view:
<script type="text/ng-template" id="notePanel" ng-controller="noteCtrl">
<div id="noteModal" class="modal fade">
<div class="modal-dialog">
<div class="form-group">
<div class="row">
<div class="col-md-offset-2 col-md-8">
<h4>{{Note.Note1}}</h4>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-offset-1 col-md-10">
{{Note.Note2}}
</div>
</div>
</div>
<div class="panel-footer clearfix">
<div class="row row-centered">
<div class="col-xs-3 col-thin col-centered">
<button type="submit" class="btn btn-primary btn-block" data-dismiss="modal" ng-click="OK()"><span class="glyphicon glyphicon-ok"></span> Agree</button>
</div>
<div class="col-xs-3 col-thin col-centered">
<button type="button" class="btn btn-default btn-block" ng-click="Cancel()"><span class="glyphicon glyphicon-remove"></span> Disagree</button>
</div>
</div>
</div>
</div>
</div>
</div>
</script>
Note controller:
appControllers.controller('noteCtrl', ['$scope', 'dataService',
function ($scope, service) {
$scope.Note;
$scope.OK = function () {
//close modal
}
$scope.Cancel = function () {
//deselect the option selected in Details view.
}
function init() {
service.getNote($scope.optionSelected, function (data) {
if (data) {
$scope.Note = data;
}
else {
console.log('Error getting note file');
//show error dialog
}
});
}
init();
}
]);

Related

How to pass value to modal in Mobile Angular Ui modal?

I am using Mobile Angular UI.
In parent window there is list of category names. I want selected category name should get updated from modal. I am able to display modal. I want to pass selected category item from parent view to modal.
My code in parent view
<div ng-controller="CategoryController as TitleCats">
<div ng-repeat="cats in TitleCats.categories">
<a href=""
ui-turn-on="titleCatUpdatemodal"
class="btn btn-default" ng-click="TitleCats.openUpdateModel(cats)"> {{cats.name}} --> Edit</a>
</div>
<div ui-content-for="modals">
<div ng-include="'pages/titleCatUpdatemodal.html'"></div>
</div>
</div>
My Modal is
<div class="modal" ui-if='titleCatUpdatemodal' ui-state='titleCatUpdatemodal'>
<div class="modal-backdrop in"></div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button class="close"
ui-turn-off="titleCatUpdatemodal">×</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p><input type="text" ng-model="cats.name" >{{ cats.name }}</p>
</div>
<div class="modal-footer">
<button ui-turn-off="titleCatUpdatemodal" class="btn btn-default">Close</button>
<button ui-turn-off="titleCatUpdatemodal" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
When i click button it opens modal but no value!
Anyone please let me know how to get value in modal. Thanks in advance.
In your controller. you should have something similar to this:
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'templates/myModal.html',
controller: 'myModalCtrl',
resolve: {
myData: function () {
//do stuff
return stuff;
}
}
});
Inside that resolve, you can fill out the function which should then be accessible in your modals controller

trigger modal popup from controller

I have a bootstrap modal popup which I fill with data from my modalcontroller. After I filled it with data I would like to show it. To be able to show the modalpopup straight away when going into the page I would like to trigger it directly. Right now I have a button which does that, but how can I do it automatic in a proper way?
<!-- Trigger the modal with a button -->
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog" ng-init="getAllItems()">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<div class="">
<form class="form-horizontal" name="form" role="form">
<div ng-repeat="item in items">
<input type="radio" name="fundselector" ng-model="item" ng-value="item"/> {{item}} <br />
</div>
</form>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
My controller:
angular.module("Modal")
.controller("ModalController",
[
"$scope", "$rootScope", "$location", "ModalService", "AuthenticationService",
function ($scope, $rootScope, $location, ModalService, AuthenticationService) {
AuthenticationService.GetCurrentWindowsUser(function(username) {
$scope.username = username;
});
$scope.getAllItems = function () {
AuthenticationService.GetCurrentWindowsUser(function (username) {
if (username) {
AuthenticationService.GetItems(username, function (items) {
$scope.items = items;
//Trigger modalpopup here
});
}
});
}
}
]);
Don't use jquery, use angular-ui.
https://angular-ui.github.io/bootstrap/#/modal
You can open the modal programmatically like below, and pass your data in in the resolve. This is copy and pasted straight from their example.
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
Find element by angular.element and hide.
var popup = angular.element("#modal-default");
//for hide model
popup.modal('hide');
//for show model
popup.modal('show');
Try something like this -
$('#yourModalId').modal('show');
To fix your example, I created a service that would open the modal and attached it to the outer controller and the modal controller. I had to remove the "modal" class from the modal because it had a display:none attribute on it. Here is a fiddle that shows what I did. However, #mgiesa's answer is better.

how to populate the scope data in modal page and how to handle the click events in modal box in angular js

Iam able to open the modal when i click on get label
how to pass the scope variable 'item' from myCtrl to modal
code for myModal.html
//below is the modal to show when we click on button in main page and display the item value in the modal-body
//when we click on the save changes how to invoke the method
<div class="modal " tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ng-click="$hide()">×</button>
<h4 class="modal-title ng-binding" ng-bind-html="title">Title</h4>
</div>
<div class="modal-body">
{{item}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$hide()">Close</button>
<button type="button" class="btn btn-primary" ng-click="modalClose()">Save changes</button>
</div>
</div>
</div>
</div>
//code main html page
<div ng-app="test">
<div ng-controller="myCtrl">
<label ng-click="openModal()">GET</label>
</div>
</div>
****//code in js****
var app = angular.module('test', []);
app.controller('myCtrl',[ui.bootstrap], function($scope,$modal) {
$scope.item= "welcome....";
$scope.openModal= function(){
var myModal = $modal({ title: 'My Title', template: 'modalEx.html', show: true });
myModal.$promise.then(myModal.show);
}
});
You need to add a resolve and controller field in modal config. For example:
resolve: {
items: function () {
return $scope.items;
}
},
controller: 'ModalInstanceCtrl'
and in your modal controller:
controller('ModalInstanceCtrl', function ($scope, $modalInstance, items)
You have items on items varible.

Modal closes and new record appears to the screen despite of problems saving in a non-blocking call to the server

Problem Statement: How to prevent model to close and caller screen to update when there is a problem in async server call? For example, say I have a screen that list books on a screen like this. It also allows to perform CRUD operations. While creating and updating a new modal opens with a new controller.
Here is the HTML:
<li ng-repeat="book in books">
<div ng-click="updateBookModelOpen('lg', book, $index)">
<p class="text-center">{{book.name}}</p>
</div>
<div class="row text-center">
<a ng-click="remove(book)" class="undecorated-link">
<button class="btn btn-danger">Delete</button>
</a>
</div>
</li>
<button ng-click="createBookModelOpen('lg')" class="btn btn-primary">Add Your Book</button>
Here is logic for opening the modal, say this is inside BooksController:
this.createBookModelOpen = function(size) {
var modalInstance = $modal.open({
templateUrl: 'create-book.html',
controller: 'CreateBookModalController',
backdrop: 'static',
keyboard: false,
size: size,
scope: $scope
});
modalInstance.result.then(function(book) {
this.books.push(book);
}, function() {
$log.info('Modal dismissed at: ' + new Date());
});
};
Here is the logic for modal controller:
.controller('CreateBookModalController', ['$scope', '$modalInstance',
function($scope, $modalInstance) {
$scope.ok = function(book) {
$modalInstance.close(book);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
}
])
Here is the modal HTML:
<section data-ng-controller="CreateBooksController as createBooksCtrl" ng-init="createBooksCtrl.init()">
<div class="modal-header">
<h3 class="modal-title">Enter Book Details</h3>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<form class="form-horizontal" name="createBookForm" novalidate>
<fieldset>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<input type="text" data-ng-model="book.name" id="name" class="form-control" placeholder="Book Name" required>
</div>
</div>
</div>
</fieldset>
</form>
</div>
</div>
</div>
<div class="modal-footer">
<div class="row">
<div class="col-md-12">
<div class="pull-right">
<button class="btn btn-primary" ng-click="cancel()">Don't Save & Close</button>
<button class="btn btn-primary" ng-click="createBooksCtrl.create(book); ok(book)">Save & Close</button>
</div>
</div>
</div>
</div>
</section>
Here is my CreateBooksClientController:
this.create = function(book) {
book.$save(function(response) {
}, function(errorResponse) {
this.errors.push(errorResponse.data.messages);
});
};
The current behavior is that when I try to save an a book with the name that is rejected by the server. I get an error from the server but since this call is nonblocking, execution to ok() proceeds because ok() is next in sequence here.
<button class="btn btn-primary" ng-click="createBooksCtrl.create(book); ok(book)">Save & Close</button>
The book does not get saved in the database. But my modal closes and the new book is displayed to the screen because of this:
modalInstance.result.then(function(book) {
this.books.push(book);
}, function() {
$log.info('Modal dismissed at: ' + new Date());
});
};
Ideally it should not have been displayed in the list here as it has not yet been saved to the database.
<li ng-repeat="book in books">
<div ng-click="updateBookModelOpen('lg', book, $index)">
<p class="text-center">{{book.name}}</p>
</div>
</li>
Expected Result: Modal should not close, ok() call should not proceed when there is an error from the service. List should not display the new book if it is not saved to the database. How do you guys handle such scenario? Any help would be highly appreciated.
If you don't need to specifically use CreateBooksClientController, you could call book.$save in the modal controller as follows:
.controller('CreateBookModalController', ['$scope', '$modalInstance', '$http'
function($scope, $modalInstance, $http) {
$scope.ok = function(book) {
book.$save(function(response) {
$modalInstance.close(book);
}, function(errorResponse) {
// Error handling
})
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
}
])
The error handling will probably have to be changed accordingly. Then the ok button will be just:
<button class="btn btn-primary" ng-click="ok(book)">Save & Close</button>

Closing all open Bootstrap modals in AngularJS?

I have created a modal that opens another modal. I want to use the second modal as a confirmation box to close the first one. I cant get it to close both modals when I click ok on the confirmation box (the second modal).
Tree.html:
<script type="text/ng-template" id="tree_item_renderer.html">
<div class="bracket-match" ng-class="match.tier == 1 ? 'bracket-match-final' : ''">
<p ng-show="match.tier == 1" class="finale-title">Finale</p>
<div class="match-content">
<div class="player-div">
<div class="bracket-player-1 bracket-player-1-tier-{{tierCount+1-match.tier}}">
<input class="input-player-1 input-player-name form-control" type="text" ng-model="match.player1" placeholder="Deltager 1">
</div>
</div>
<div class="player-div border-bottom">
<div class="bracket-player-2">
<input class="input-player-2 input-player-name form-control" type="text" ng-model="match.player2" placeholder="Deltager 2">
</div>
</div>
</div>
<div ng-show="match.tier == 1 && showthirdplace && tierCount >= 2" class="third-place" ng-model="thirdplace">
<p class="finale-title">3. plads</p>
<div class="match-content">
<div class="player-div">
<div class="bracket-player-1 bracket-player-1-tier-{{tierCount+1-match.tier}}">
<input class="input-player-1 input-player-name form-control" type="text" ng-model="match.player1" placeholder="Deltager 1">
</div>
</div>
<div class="player-div border-bottom">
<div class="bracket-player-2">
<input class="input-player-2 input-player-name form-control" type="text" ng-model="match.player2" placeholder="Deltager 2">
</div>
</div>
</div>
</div>
</div>
<div class="bracket-column">
<div ng-repeat="match in match.previousMatches" ng-include="'tree_item_renderer.html'" />
</div>
</script>
<script type="text/ng-template" id="tournament-tree.html">
<div class="row modal-footer-btns">
<button class="btn btn-primary" ng-click="ok()">GEM</button>
<button class="btn btn-warning btn-xs" ng-click="openAlertBox()" type="button" data-dismiss="modal">LUK, uden at gemme</button>
</div>
<div class="row" style="margin-bottom:15px;">
<a ng-click="addMatchTier()" class="btn btn-primary"><i class="glyphicon glyphicon-plus"></i></a>
<a ng-click="removeMatchTier()" ng-class="tierCount > 1 ? 'btn btn-primary' : 'btn btn-default'"><i class="glyphicon glyphicon-minus"></i></a><br />
</div>
<div class="row tournament-tree">
<div ng-repeat="match in finalMatch">
</div>
<div class="bracket-column">
<div ng-repeat="match in finalMatch" ng-include="'tree_item_renderer.html'"></div>
</div>
</div>
</script>
<script type="text/ng-template" id="openAlertBox.html">
<div class="modal-header">
<h3 class="modal-title"></h3>
</div>
<div class="modal-body"> </div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">Ja</button>
<button class="btn btn-warning" ng-click="cancel()">Annuller</button>
</div>
</script>
Categories.html:
<div class="row">
<div class="modal-header">
<h3 class="modal-title"></h3>
</div>
</div>
<div ng-controller="CategoriesController">
<a ng-click="add()" class="btn btn-tree btn-primary" style="margin-top:15px;">Tilføj hovedkategori</a>
<p ng-repeat="data in nodes" ng-include="'category_item_renderer.html'"></p>
<ng-include src="'Modules/TournamentTree/Tree.html'"></ng-include>
</div>
<script type="text/ng-template" id="category_item_renderer.html">
<div class="category-style">
<div class="push-cat-btn">
<a ng-click="add(data)" class="btn btn-primary btn-sm"><i class="glyphicon glyphicon glyphicon-plus"></i></a>
<a ng-hide="data.nodes.push()" ng-click="openTournamentTree(data)" class="btn btn-info btn-xs">Turnering</a>
</div>
</div>
<p class="push" ng-repeat="data in data.nodes" ng-include="'category_item_renderer.html'"></p>
</script>
<script type="text/ng-template" id="TournamentTreeModal.html">
<div class="modal-header">
<h3 class="modal-title"></h3>
</div>
<div class="modal-body">
<div class="include-tree" ng-include="'tournament-tree.html'"></div>
</div>
<div class="modal-footer">
</div>
</script>
TreeController.js:
angular.module('tournamentTree', ['ui.bootstrap']);
angular.module('tournamentTree').controller("TreeController", ['$scope', '$modal', '$modalInstance', 'guidGenerator', function ($scope, $modal, $modalInstance, guidGenerator) {
$scope.openAlertBox = function () {
var alertBoxInstance = $modal.open({
templateUrl: 'openAlertBox.html',
controller: 'TreeController',
scope: $scope,
size: 'xs',
resolve: {
}
});
};
$scope.ok = function () {
$scope.close();
$scope.$parent.close();
}
$scope.cancel = function () {
$scope.close();
$scope.$parent.dismiss('cancel');
};
categoriController.js:
angular.module('tournamentCategories').controller("CategoriesController",
['$scope', '$modal', 'guidGenerator', 'eventBus', domainName + "Service", 'TournamentCategoryModelFactory',
function ($scope, $modal, guidGenerator, eventBus, domainService, modelFactory) {
$scope.openTournamentTree = function () {
var modalInstance = $modal.open({
templateUrl: 'TournamentTreeModal.html',
controller: 'TreeController',
scope: $scope,
size: 'wide-90',
backdrop: 'static',
keyboard: false,
resolve: {
}
});
modalInstance.result.then(function (selectedItem) {
//$scope.selected = selectedItem;
}, function () {
//$log.info('Modal dismissed at: ' + new Date());
});
};
}]);
You can use $modalStack from ui.bootstrap to close all instances of $modalInstance
$modalStack.dismissAll(reason);
This is how i got it working in my project without using any factory or additional code.
//hide any open bootstrap modals
angular.element('.inmodal').hide();
I have a timeout function that emits logout as $rootScope.$emit('logout'); and the listener in my service is as follows:
$rootScope.$on('logout', function () {
//hide any open bootstrap modals
angular.element('.inmodal').hide();
//do something else here
});
If you want to hide any other modals such as angular material dialog ($mdDialog) & sweet alert dialog's use angular.element('.modal-dialog').hide(); & angular.element('.sweet-alert').hide();
I don't know if this is the right approach , but it works for me.

Resources