Related
I have a very strange error. Whenever I click an event on my full calendar, a modal is supposed to appear except, it freezes the entire page before opening up.
frozen modal
in the link above, the thin grey line at the top is the modal.
Bootstrap Modal popping up but has a "tinted" page and can't interact
I tried the following solution but it did not seem to make a difference in my case. Can anyone suggest a fix/faced a similar issue before?
directive.js
myApp.directive('msResourceCalendarDirective', function ($window, $timeout, $http) {
return {
restrict: 'AE',
templateUrl: '/client/resourceCalendarDirective/view.html?v=1',
controller: function($scope, $element, $attrs, $uibModal) {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
// Open modal from modal
$scope.alertOnEventClick = function (eventObj) {
console.log('Opening modal...');
var modalInstance = $uibModal.open({
animation: true,
templateUrl: '/client/resourceCalendarDirective/modal.html',
backdrop: false,
keyboard: true,
resolve: {
event: function () {
return eventObj;
}
}
});
// Scope apply here to make modal show up
$scope.$evalAsync(function() {
modalInstance.result.then(
function (event) {
console.log('Modal closed at: ' + new Date());
console.log(event);
//$scope.events.push(event);
},
function () {
console.log('Modal dismissed at: ' + new Date());
}
);
});
};
// empty array of events
$scope.events = [];
$scope.myevents = function(start, end, timezone, callback) {
$http.get('/api/v1/sample').then(function(response) {
//var events = [];
angular.forEach(response.data, function(event,key){
$scope.events.push({
id: event._id,
title: event.title,
start: event.startDateTime,
end: event.endDateTime
});
});
callback($scope.events);
});
};
/* config calendar object */
$scope.uiConfig = {
calendar: {
height: 650,
editable: true,
header: {
left: 'month basicWeek basicDay',
center: 'title',
right: 'today prev, next'
},
eventClick: $scope.alertOnEventClick
// eventDrop: $scope.alertOnDrop,
// eventResize: $scope.alertOnSize
}
};
// linking event array to calendar to be displayed
$scope.eventSources = [$scope.myevents];
}
}
});
modal.html
<!-- Update Modal -->
<div class="modal" id="calendarModal.html" >
<div class="modal-dialog">
<div class="modal-content" >
<div class="modal-header">
<h3>Edit Resource</h3>
</div>
<div class="modal-body">
<div class="form-group row">
<div class="col-xs-6">
<label for="resourceTitle">Title</label>
<input id="resourceTitle" class="form-control" type="text" name="title" ng-model="sample.title">
</div>
</div>
<div class="form-group">
<ms-date-time-picker ng-model="sample.startDateTime" placeholder="From" id="dateFrom"></ms-date-time-picker>
</div>
<div class="form-group">
<ms-date-time-picker ng-model="sample.endDateTime" placeholder="To" id="dateTo"></ms-date-time-picker>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="updateResource()" >Update Resource</button>
<button class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Maybe you should try to increase z-index property of modal?
Try
<div class="modal-dialog" id="my-modal">
And then from resolve:
event: function () {
return eventObj;
}
showModal: () {
setTimeout(function () {
$('#my-modal').parent().css('z-index', '10000')
}, 5000);
}
Dirty solution, but may be a solution in your case. Timeout is added to allow everything to render (#my-modal) has to be initialized and visible.
I am showing a modal popup on click of a button in a row in ng grid.So to get a form in the modal popup i am filling it with JSON Schema as follows
The Html Of Modal Pop Up is
<div class="modal-header">
<h3 class="modal-title">Edit Row</h3>
</div>
<div class="modal-body">
<form sf-schema="schema" sf-form="form" sf-model="entity"></form>
</div>
<div class="modal-footer">
<button class="btn btn-success" ng-click="save()">Save</button>
<button class="btn btn-warning" ng-click="$close()">Cancel</button>
</div>
</div>
The schema is put into the constant like below in an external js file:
var app = angular.module("myApp", ['ngGrid','ui.bootstrap']);
app.constant('UserPopUpSchema', {
type: 'object',
properties: {
FullName: { type: 'string', title: 'FullName' },
UserName: { type: 'string', title: 'UserName' },
Password: { type: 'string', title: 'Password' },
EmailAddress: { type: 'string', title: 'EmailId' },
Phone: {type:'string',title:'phNum'}
}
});
So on click of a row in ng-grid I am executing a function called edit row ,which would open the pop up and fill the form according to the constant.
$scope.editRow = function (grid,row) {
$modal.open({
templateUrl: 'PopUpTemplate.htm',
controller:['$modalInstance', 'grid', 'row','UserPopUpSchema', function($modalInstance,grid,row){
schema = 'UserPopUpSchema';
entity = angular.copy(row.entity);
form = [
'FullName',
'UserName',
'Password',
'EmailId',
'phNum'
];
}],
resolve: {
grid: function () { return grid; },
row: function () { return row; }
}
});
};
But here I am a bit confused on how to inject a constant to a controller function .As a result the modal appear with a blank form.
Appreciate any help!!
Try this
$modal.open({
templateUrl: 'PopUpTemplate.htm',
controller: function ($modalInstance, grid, row, UserPopUpSchema) {
// Do Stuff
},
resolve: {
grid: function () {
return grid;
},
row: function () {
return row;
},
UserPopUpSchema: function () {
return UserPopUpSchema;
}
}
});
app.controller('Myctrl',function($scope,UserPopUpSchema) {
$scope.editRow = function (grid,row) {
$modal.open({
templateUrl: 'PopUpTemplate.htm',
controller:['$modalInstance', 'grid', 'row','UserPopUpSchema', function($modalInstance,grid,row){
schema = 'UserPopUpSchema';
entity = angular.copy(row.entity);
form = [
'FullName',
'UserName',
'Password',
'EmailId',
'phNum'
];
}],
resolve: {
grid: function () { return grid; },
row: function () { return row; }
UserPopUpSchema: function () { return UserPopUpSchema; }
}
});
};
});
and in the modal instance controller inject the UserPopUpSchema along with grid and row
$modal.open() accept a "resolve" property in which you can pass all the data you want.
$modal.open({
templateUrl: 'templateUrl',
controller: 'controllerName',
resolve: {
data: function(){
// Here, return a JSON object containing all the data you want to pass to the controller.
}
}
});
Then your controller will look like this :
yourApp.controller('controllerName', function ( $scope, $modalInstance, data ){
// Here, using data, you can access the JSON object you passed previously.
});
I am trying to use a Angular/bootstrap modal to edit MVC ApplicationUser scaffolded views. I have a found a few examples, they are mostly jquery. I found one that works well using jquery-ui. I want to be consistent with my modals so I need to make it work with angular-ui or plain bootstrap. I am not sure how this is calling the MVC controller for the data binding.
Working Jquery-ui example
<script type="text/javascript">
$(document).ready(function () {
$.ajaxSetup({ cache: false });
$(".editDialog").live("click", function (e) {
var url = $(this).attr('href');
$("#dialog-edit").dialog({
title: 'Edit Customer',
autoOpen: false,
resizable: false,
height: 355,
width: 400,
show: { effect: 'drop', direction: "up" },
modal: true,
draggable: true,
open: function (event, ui) {
$(this).load(url);
},
});
$("#dialog-edit").dialog('open');
return false;
});
});
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FullName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }, new { #class = "editDialog" })|
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
</td>
</tr>
}
</tbody>
<div id="dialog-edit" style="display: none"> </div>
Here is how I use angular to open a modal with a api call.
$scope.editLocation = function (id) {
$scope.close();
var deferred = $q.defer();
$http({ method: 'get', url: '/api/Locations/' + id })
.success(function (model) {
deferred.resolve(model);
$scope.model = model;
}).error(function (error) {
deferred.reject(error);
}).then(function () {
$modal.open({
templateUrl: "EditLocationModal.html",
controller: 'ModalInstanceController',
resolve: {
model: function () {
return $scope.model;
}
}
});
})
return deferred.promise;
}
UPDATE
$scope.editUser = function (id) {
$modal.open({
templateUrl: "Modals/ApplicationUserModal.html",
controller: 'ModalInstanceController',
resolve: {
model: function () {
return $scope.model;
}
}
});
};
View
<div class="card-body card-padding" ng-controller="ApplicationUserController">
<div class="table-responsive">
<table class="table table-striped table-vmiddle">
<thead>
<tr>
<th>Full Name</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FullName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", null, new { ng_click = "editUser(item.Id)" })
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
UPDATE 2
This syntax
#Html.ActionLink("Edit", "Edit", null, new { ng_click = "editUser(" + item.Id + ")" })
is throwing this error.
Error: [$parse:syntax] Syntax Error: Token 'bc05f5' is unexpected, expecting [)] at column 12 of the expression [editUser(87bc05f5-35c2-4278-a528-b7e237922d4e)] starting at [bc05f5-35c2-4278-a528-b7e237922d4e)].
http://errors.angularjs.org/1.3.15/$parse/syntax?p0=bc05f5&p1=is%20unexpected%2C%20expecting%20%5B)%5D&p2=12&p3=editUser(87bc05f5-35c2-4278-a528-b7e237922d4e)&p4=bc05f5-35c2-4278-a528-b7e237922d4e)
I am not sure how this is calling the MVC controller for the data
binding.
Just to clue you in on the interesting parts
// 1. here it binds a "click" event to all elements with class "editDialog"
$(".editDialog").live("click", function (e) {
// 2. here it fetches the HREF attribute of that element
var url = $(this).attr('href');
$("#dialog-edit").dialog({
title: 'Edit Customer',
autoOpen: false,
resizable: false,
height: 355,
width: 400,
show: { effect: 'drop', direction: "up" },
modal: true,
draggable: true,
open: function (event, ui) {
// 3. And here it loads that HREF attribute in the modal
$(this).load(url);
},
});
$("#dialog-edit").dialog('open');
return false;
});
That's basically all of the "data binding" going on in the jquery version. As you can see it's really not anything fancy.
You'd probably like to do something more elegant, like setting up an angular directive for your editDialog or somesuch.
EDIT:
I re-read how you init your modal and if I understood everything correctly you should be able to do something like this (not razor-savvy enough to be 100% on the syntax but you get the idea)
#Html.ActionLink("Edit", "Edit",
new { id = item.Id },
new { ng_click = "editUser('" + #item.Id + "')" })
Also, you might or might not need to scope editUser inside ng-click.
This code to show bootstrap popup
<script type="text/javascript">
$(document).ready(function () {
$.ajaxSetup({ cache: false });
$(".editDialog").live("click", function (e) {
$('#myModalContent').load(this.href,function(){
$('#myModal').modal({
keyboard: true
},'show');
bindForm(this);
});
return false;
});
function bindForm(dialog){
$('form',dialog).submit(function(){
$.ajax({
url:this.action,
type:this.method,
data:$(this).serialize(),
success: function(result){
if(result.success)
{
$('#myModal').modal('hide');
$('#YourFormId').load(result.url);
}
else
{
$('#myModalContent').html(result);
bindForm(dialog);
}
}
});
return false;
)};
</script>
In your parent view:
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
</div>
</div>
In Edit in popup build the code into
<div class="modal-content">
<div class="modal-header">
//Your heading
<div class="modal-body">
//your body content
</div>
<div class="modal-footer">
//your footer
</div>
</div>
Example for delete with bootstrap modal and mvc model:(asp.net mvc6)
html page :
<div ng-controller="CustomersCtrl">
//template for modal with bootstrap
<div class="modal-header" style="background-color:#54a0fc !important;">
<button type="button" class="close" data-dismiss="modal" aria-label="Close" ng-click="cancel()"><span aria-hidden="true">×</span></button>
<h3>Delete</h3>
</div>
<div class="modal-body">
<table class="table">
<thead>
</thead>
<tbody>
<tr>
<td>Last Name : </td>
<td>{{customer.LastName}}</td>
</tr>
<tr>
<td>First Name : </td>
<td>{{customer.FirstName}}</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer" style="background-color:#54a0fc !important;">
<button ng-click="delete(customer.CustomerID)" class="btn btn-danger btn-lg">Delete</button>
<button ng-click="cancel()" class="btn btn-default btn-lg">Cancel</button>
</div>
in your controller think to add ['ui.bootstrap'] in your app.js:
CustomersCtrl.$inject = ['$scope', '$http', '$location', '$modal'];
function CustomersCtrl($scope, $http, $location, $modal) {
//function to open Delete modal
$scope.openDelete = function (id) {
var modalInstance = $modal.open({
templateUrl: 'Modals/Customers/delete.html',
controller: $scope.modalDelete,
//matches of the id of your item to recover object model in the controller of the modal
resolve: {
id: function () {
return id
}
}
});
}
//controller of the modal. Inside you can recover your object with ajax request
$scope.modalDelete = function ($scope, $modalInstance, id) {
if (angular.isDefined(id)) {
var reqGetCustomer = $http({ url: '/api/Customers/' + id, method: 'GET' });
reqGetCustomer.success(function (dataResult) {
$scope.customer = dataResult;
});
} else { alert('id is undefined'); }
//function to close modal
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
}
}
$scope.delete = function (id) {
var customer = getCustomer(id);
var reqDeleteCustomer = $http({ url: '/api/customers/' + id, method: 'DELETE' });
reqDeleteCustomer.success(function (dataResult) {
$scope.cancel();
});
$scope.customers = getListCustomers();
}
}
I hope this will help you
I am using Twitter-Bootstrap Modal. I set a close icon on Modal header. I need to active this icon to close the Modal.
<div class="modal-content json-modal-body" id="full-width" ng-controller="projectdetailsController" close="CloseModal()">
<div class="modal-header modal-header-confirm">
<h4 class="modal-title ng-binding">
<span class="glyphicon glyphicon-indent-left"></span>{{modalOptions.headerText}}
<a type="button" title="Close" data-dismiss="modal"><i ng-click="CloseModal()" class="glyphicon glyphicon-remove icon-arrow-right pull-right"></i></a>
</h4>
</div>
<div class="modal-body">
<pre class="Modal-pre" ng-bind-html="modalOptions.bodyText"></pre>
</div>
</div>
Controller:
var modalInstance=$scope.showJSON = function(){
var modalOptions = {
headerText: ' JSON Schema View',
bodyText: 'jsonSchema'
};
var modalDefaults = {
templateUrl: 'app/partials/jsonModal.html'
};
modalService.showModal(modalDefaults, modalOptions).then(function (result) {
});
}
$scope.CloseModal = function () {
$modalInstance.close();
}
I am using ng-click="CloseModal()" to close the modal. I also declared close="CloseModal()" on the parent div. How can I solve this?
I have an AngularJs controller for this modal. Can I use the controller?
You have to declare the function CloseModal() in your controller
If you use angular-ui bootstrap it should look like this:
['$scope', '$modalInstance', function($scope, $modalInstance){
...
$scope.CloseModal = function () {
$modalInstance.close();
}
Follow these steps:
var app = angular.module('myApp',['ui.bootstrap']);
//controller for modal
app.controller('modalCtrl',['$scope','$modalInstance', function ($scope,$modalInstance) {
'use strict';
$scope.cancel = function () {
$modalInstance.dismiss();
};
Second controller:
app.controller('Ctrl',['$scope','$modal', function ($scope,$modal) {
$scope.openModal= function () {
$modal.open({
backdrop: true,
keyboard: false,
backdropClick: false,
templateUrl: "path of your modal HTML",
dialogClass: "modal-content",
controller: 'modalCtrl',
});
}
I am new in angularJs and I have an application that using angular modal and jqGrid. (I know that this is not good. But for some reason I must work with two, now.)
My modal content loads with a templateUrl.
<div ng-controller="SearchPerson as ctrl">
<div class="modal-body">
<table id="list"></table>
<div id="pager"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-link" data-dismiss="modal" ng-click="$close()">CLOSE</button>
<button type="button" class="btn btn-primary" ng-click="ctrl.CLOSE()">Save changes</button>
</div>
</div>
and for create I have this code:
$(function () {
$("#list").jqGrid({
url: "/Home/List",
datatype: "json",
mtype: 'GET',
colNames: [" ", "FirstName", "LastName"],
colModel: [
{
width: 30,
sortable: false,
formatter: function (cellvalue, options, rowObject) {
return 'SELECT';
},
},
{
name: "FirstName",
width: 60,
},
{
name: "LastName",
width: 90
}
],
jsonReader: {
page: "Page",
total: "Total",
records: "Records",
root: "Rows",
repeatitems: false,
cell: "cell",
id: "id",
userdata: "userdata",
},
pager: "#pager",
});
});
and for open modal I write this code:
angular.module('AngularModal', ['ui.bootstrap']);
angular.module('AngularModal').controller('ModalDemoCtrl', function ($scope, $modal) {
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: '/Home/SearchGrid',
controller: 'ModalInstanceCtrl',
size: size,
backdrop: 'static',
});
modalInstance.result.then(function () {
//
}, function () {
//
});
};
});
angular.module('AngularModal').controller('ModalInstanceCtrl', function ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
angular.module('AngularModal').controller('SearchPerson', function ($http, $modalStack) {
});
What I want is: when I click SELECT link in my grid, alert FirstName and then close the modal.
How to do this?
It is noteworthy that when I click CLOSE button, modal close. And also when I click "Save changes" buton, the modal will close.
But when I click SELECT link, modal does not close. While I write both ng-click of SELECT and "Save Change" for it.
Your code would definitely not work. For ng-click, the context of the expression is the current $scope, while for href="javascript:expression" the context is the global, or saying window.
For your situation, I would definitely suggest you try some other grid libraries which are more compatible with AngularJS (like http://angular-ui.github.io/ng-grid/ or http://ui-grid.info/). That may save tons of time.
Otherwise, if you really really insist on using jqGrid, you may need to wrap it into a directive manually by yourself. In your application, you may need to consider how to "angularize" the html snippet generated for the formatter function.
formatter: function (cellvalue, options, rowObject) {
var html = '<a ng-click="ctrl.Select()">SELECT</a>';
var linkFunc = $compile(html);
linkFunc(scope); // the scope in which you have the `ctrl.Select()` function.
return html;
},
$compile: https://docs.angularjs.org/api/ng/service/$compile
Then you will be able to call angular scope functions.
However, in my opinion, this is not a good practice. If any possible, find a replacement library, please.