Modal Form Submission without refresh - javascript

I have a modal window that pops up when I want to add a new project to my dashboard. I have gotten it to work with jquery post however, I cannot prevent it from refreshing. What I want to do is after the project is added to the database, show a success message and close the modal window after few seconds and not refresh the page (parent page of modal).
Here is my modal
<div class="modal fade" id="add-project-dialog" tabindex="-1" role="dialog" aria-labelledby="basicModal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="myModalLabel">Add a new Project</h4>
</div>
<div class="modal-body">
<h3>New Project:</h3>
<form class="form-horizontal" id="add-project-form" action="/projects/add" method="POST">
<fieldset>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="name">Project Name</label>
<div class="col-md-4">
<input id="name" name="name" type="text" placeholder="" class="form-control input-md">
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="description">Project Description</label>
<div class="col-md-4">
<input id="description" name="description" type="text" placeholder="" class="form-control input-md">
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="project_state">Project State</label>
<div class="col-md-4">
<input id="project_state" name="project_state" type="text" placeholder="" class="form-control input-md">
</div>
</div>
</fieldset>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button id="add-btn" class="btn" type="submit">Add</button>
</div>
</form>
</div>
</div>
Here is my project-dashboard.js
AddProject = function(){
$(document).ready(function() {
$("#submit").submit(function(event){
event.preventDefault();
$.ajax({
url: "/projects/add",
type:"POST",
data:
{
'name': $('#name').val(),
'description': $('#description').val(),
'project_state': $('#project_state').val()
}
});
});
});
}
My views.py
class AddProject(webapp2.RedirectHandler):
def get(self):
template_values = {
#'greetings': greetings,
#'url_linktext': url_linktext,
}
path = os.path.join(os.path.dirname(__file__), '../templates/project-add.html')
self.response.write(template.render(path, template_values))
def post(self):
project = Project()
project.name = self.request.get('name')
project.description = self.request.get('description')
project.project_state = self.request.get('project_state')
time.sleep(2)
project.put()
self.redirect('/projects')
I have tried removing the self.redirect('/projects') however that only takes me to a blank page that is /projects/add (that is the action in the form).

The issue is that you added .ready(foo) handler inside of the AddProject function. I suppose that document is loaded when AddProject is called.
Another issue is that in your HTML, the form has id add-project-form, so you should do $("#add-project-form") instead of $("#submit").
$(document).ready(function () {
$("#add-project-form").submit(function(event){
event.preventDefault();
$.ajax({
url: "/projects/add",
type:"POST",
data:
{
'name': $('#name').val(),
'description': $('#description').val(),
'project_state': $('#project_state').val()
}
});
});
});
});
Take ready handler outside of the AddProject function and it should work (the submit handler is added).

Edit: After some debugging, the answer was to use the right id and proper placing of the javascript code, as noted by the comments.
For starters, a refresh is easy to avoid, just make sure to prevent the default event from running; since you're using jQuery, I would recommend doing return false to end the function, since it both 'prevents default' and 'stops propagation'.
So the first thing you should do is check if your javascript code is actually running and not erring in the middle of execution. If everything is fine there, the worst case is that the project is not actually added (server side error) but the page should not refresh.
Your server side code has nothing to do with the refresh (if it's being properly hijacked), so the response doesn't really matter, I would actually return the id of the new project (so you could provide a link for the newly created item or something like that), but i digress...

Here is a snippet for not only closing modals without page refresh but when pressing enter it submits modal and closes without refresh
I have it set up on my site where I can have multiple modals and some modals process data on submit and some don't. What I do is create a unique ID for each modal that does processing. For example in my webpage:
HTML (modal footer):
<div class="modal-footer form-footer"><br>
<span class="caption">
<button id="PreLoadOrders" class="btn btn-md green btn-right" type="button" disabled>Add to Cart <i class="fa fa-shopping-cart"></i></button>
<button id="ClrHist" class="btn btn-md red btn-right" data-dismiss="modal" data-original-title="" title="Return to Scan Order Entry" type="cancel">Cancel <i class="fa fa-close"></i></a>
</span>
</div>
jQUERY:
$(document).ready(function(){
// Allow enter key to trigger preloadorders form
$(document).keypress(function(e) {
if(e.which == 13) {
e.preventDefault();
if($(".trigger").is(".ok")) //custom validation dont copy
$("#PreLoadOrders").trigger("click");
else
return;
}
});
});
As you can see this submit performs processing which is why I have this jQuery for this modal. Now let's say I have another modal within this webpage but no processing is performed and since one modal is open at a time I put another $(document).ready() in a global php/js script that all pages get and I give the modal's close button a class called: ".modal-close":
HTML:
<div class="modal-footer caption">
<button type="submit" class="modal-close btn default" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
jQuery (include global.inc):
$(document).ready(function(){
// Allow enter key to trigger a particular class button
$(document).keypress(function(e) {
if(e.which == 13) {
if($(".modal").is(":visible")){
$(".modal:visible").find(".modal-close").trigger('click');
}
}
});
});
Now you should get no page refreshes on any of your modals if u follow these steps.

Related

Modal window comment editing module (editable text)

I want to make, that during the ediditing comment action, I have modal window with comment text written inside textarea, and it is editable without deleting all text with clicking. I tried just to put value inside textarea or placing it in placeholder. But both options are wrong and doesnt work.
Can someone take a look on this code and give me an advice, how should I take for it.
editComment.html
<div class="modal-header">
<h3 class="modal-title" id="modal-title">Edytuj komentarz</h3>
</div>
<div class="modal-body" id="modal-body">
<div class="row">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-12 form-group">
<label>Treść</label>
<textarea class="form-control input-sm"
name="description"
ng-maxlength="512"
ng-model="$ctrl.selected"
rows="6">{{comment.value()}}</textarea>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-raised btn-primary"
type="button"
ng-disabled="!$ctrl.selected"
ng-click="$ctrl.ok()">Zapisz
</button>
<button class="btn btn-raised btn-warning"
type="button"
ng-click="$ctrl.cancel()">Anuluj
</button>
</div>
editComment.js
(function() {
'use strict';
angular.module('settlerApplication').controller('EditCommentCtrl', function($uibModalInstance) {
var $ctrl = this;
$ctrl.ok = function() {
$uibModalInstance.close($ctrl.selected);
};
$ctrl.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
});
})();
I'm not sure to understand what you are trying to achieve. But anyway : if you want to init your textarea's ng-model with $ctrl.foo (comment.value() in your case, from what I understood), you should either :
In the controller, init your $ctrl.selected variable with this value :
$ctrl.selected = $ctrl.foo;
Or, in your template, use ng-init :
<textarea class="form-control input-sm"
ng-init="$ctrl.selected = $ctrl.foo"
name="description"
ng-maxlength="512"
ng-model="$ctrl.selected"
rows="6"></textarea>
Ok, so I am going to explain that a little.
I have modal window like that:
I want to edit existing comments in this window. And so I want my comment appears instead of text: "Komentarz" (under: "Treść" after clicking in there). And I want that comment text to be editable, so I dont have to write it down again (put the whole text to that area). Is it make it a little better explained about my goal?

Converting Bootstrap 3 remote modal to Bootstrap 4 modal with parameters

So in the near future my shop is going to upgrade to Bootstrap 4 but we cannot do this until we solve the issue with using remote modals. Here is an example of how we load our modals. The reason we use remote modals is because the modal-body is dynamic and may use different file based on the url. I have heard that using jQuery("#newsModal").on("load",..) is an alternative but how could I do this? I found this but I am not sure how my anchor would look and how to build the url to load the remote data.
Global PHP include file:
<div id="NewsModal" class="modal fade" tabindex="-1" role="dialog" data-
ajaxload="true" aria-labelledby="newsLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="newsLabel"></h3>
</div>
<div class="noscroll-modal-body">
<div class="loading">
<span class="caption">Loading...</span>
<img src="/images/loading.gif" alt="loading">
</div>
</div>
<div class="modal-footer caption">
<button class="btn btn-right default modal-close" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
modal_news.php file:
<form id="newsForm">
<div id="hth_err_msg" class="alert alert-danger display-hide col-lg-12 col-md-12 col-sm-12 col-xs-12">
You have some errors. Please check below.
</div>
<div id="hth_ok_msg" class="alert alert-success display-hide col-lg-12 col-md-12 col-sm-12 col-xs-12">
✔ Ready
</div>
<!-- details //-->
</form>
Here is how we trigger the modals :
<a href="#newsModal" id="modal_sbmt" data-toggle="modal" data-target="#newsModal"
onclick="remote='modal_news.php?USER=yardpenalty&PKEY=54&FUNCTION=*GENERAL'; remote_target='#NewsModal .noscroll-modal-body'">
<span class="label label-icon label-info">
<i class="fa fa-bullhorn"></i>
</span>
Promotional Ordering
</a>
I think I need to do something like this when building anchor dynamically:
a) Replace paramters with data-attrs
b) Use the event invoker to get the data-attrs using event.target.id
Thanks to Tieson T. and this post I was able to effectively pass parameters to the remote modal using this technique except if you have multiple modals
I have also included some helpful techniques inside this example as to how you may pass parameters to the remote modal.
bootstrap_modal4.php:
<div class="portlet-body">
Add Attendee <i class="fa fa-plus"></i>
</div>
<!-- BEGIN Food Show Attendee Add/Edit/Delete Modal -->
<div id="attendee" class="modal fade" tabindex="-1" role="dialog" data-ajaxload="true" aria-labelledby="atnLabel" aria-hidden="true">
<form id="signupForm" method="post">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<label id="atnLabel" class="h3"></label><br>
<label id="evtLabel" class="h6"></label>
</div>
<div class="modal-body">
<div class="loading"><span class="caption">Loading...</span><img src="/images/loading.gif" alt="loading"></div>
</div>
<div class="modal-footer">
<span class="caption">
<button type="button" id="add_btn" class="btn btn-success add-attendee hidden">Add Attendee <i class="fa fa-plus"></i></button>
<button type="button" id="edit_btn" class="btn btn-info edit-attendee hidden">Update Attendee <i class="fa fa-save"></i></button>
<button type="button" id="del_btn" class="btn btn-danger edit-attendee hidden">Delete Attendee <i class="fa fa-minus"></i></button>
<button class="btn default modal-close" data-dismiss="modal" aria-hidden="true">Cancel</button>
</span>
</div>
</div>
</div>
</form>
</div>
<script>
jQuery(document).ready(function() {
EventHandlers();
});
function EventHandlers(){
$('#attendee').on('show.bs.modal', function (e) {
e.stopImmediatePropagation();
if($(this).attr('id') === "attendee"){
// Determines modal's data display based on its data-attr
var $invoker = $(e.relatedTarget);
var fscode = $invoker.attr('data-fscode');
console.log(fscode);
// Add Attendee
if($invoker.attr('data-atnid') === "add"){
$("#atnLabel").text("Add New Attendee");
$(".add-attendee").removeClass("hidden");
}
else{ //edit/delete attendee
$("#atnLabel").text("Attendee Maintenance");
$(".edit-attendee").removeClass("hidden");
}
//insert hidden inputs
//add input values for post
var hiddenInput = '<INPUT TYPE=HIDDEN NAME=FSCODE VALUE="' + fscode + '"/>';
$("#signupForm").append(hiddenInput);
}
});
$('#attendee').on('hidden.bs.modal', function (e) {
$(".edit-attendee").addClass("hidden");
$(".add-attendee").addClass("hidden");
$("#signupForm input[type='hidden']").remove();
});
// BOOTSTRAP 4 REMOTE MODAL ALTERNATIVE FOR BOOTSTRAP 3v-
$('#add-attendee').on('click', function(e){
$($(this).data("target")+' .modal-body').load($(this).data("remote"));
$("#attendee").modal('show');
});
}
</script>
bootstrap_remote_modal4.php:
<form id="signupForm">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
Hello World!
</div>
</form>
<script>
$(document).ready(function(){
console.log('<?php echo $_GET["USERNAME"]?>'); //passed through url
});
</script>
NOTE: I am having problems with event propagation during the show.bs.modal event which I have a global show.bs.modal that is propagating up to this event handler due to multiple modals so if you have multiple modals make sure to handle them correctly.
Here is a screen shot of the results which clearly show propagation is taking place but the parameter passing techniques are working.
You might find it easier to use something like Bootbox.js, which can be used to dynamically create Bootstrap modals.
Given what you've shown, it would work something like:
trigger modal
with
$(function(){
$('.show-modal').on('click', function(e){
e.preventDefault();
var url = $(this).attr('href');
$.get(url)
.done(function(response, status, jqxhr) {
bootbox.dialog({
title: 'Your Title Here',
message: response
});
});
});
});
This assumes response is an HTML fragment.
Bootbox hasn't officially been confirmed to work with Bootstrap 4, but I haven't run into any problems with it yet (modals seem to be one of the few components that don't have updated markup in BS4).
Disclaimer: I am currently a contributor to Bootbox (mainly updating the documentation and triaging issues).
If you must use only the Bootstrap modal, you're actually after load(). You would probably do something like:
$(function(){
$('.show-modal').on('click', function(e){
e.preventDefault();
var url = $(this).attr('href');
var dialog = $('#NewsModal').clone();
dialog.load(url, function(){
dialog.modal('show');
});
});
});

how to make JS wait for confirmation modal

This might be really stupid but I am not seeing anything straight here, help me out please.
so their is this guy :
As you can see upon click the function changeBlock is called
this.changeBlock = function() {
var flag = confirm("You sure you want to block this user ?");
if(flag){
blockUser(this.postId);
if(this.block() != ""){
this.block("Blocked");
this.pointId(AS.currentUserDetails.name);
return "Blocked";}
}
}
and somewhere lie the function blockUser
function blockUser(post_id) {
var blockUser = AS.baseUrl + "blockNewUser";
$.ajax({
url:blockUser,
type:"POST",
data:{postId : post_id},
success:function(data) {
// `request` seems a very strange name; perhaps `data` or `response`?
},
error: function(){
// You can't use `document.write` after the page has been parsed
}
});
}
My problem is that I cant use confirm() for confirming block or cancel.
I will have to use a html modal which is used through out the website.
If at some point of the execution I add
$('#my-modal').modal('show');
then though the modal appears but rest of the execution takes place without waiting for me to select yes or no.
And if by some magic I manage to make JS wait for selection, How will I know what was selected ?
what should I do ?
I cannot use any third party modals.
here is the modal I want to use :
<div id="block-confirm-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-backdrop="static">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-body">
<div class="clearfix side-space">
<h3 class="modal-title text-center">Are you sure you want to Block this user ?</h3>
</div>
<form id="form-block-confirm" name="" method="post" action="" class="form-horizontal">
<div class="clearfix side-space">
<div class="clearix text-center">
<button type="submit" class="btn btn-saffron btn-introduce" id='block-confirm-button'>Block</button>
<button type="submit" class="btn btn-saffron btn-introduce" id='block-cancel-button'>Cancel</button>
<!--input type="submit" name="submit" class="btn btn-saffron btn-introduce" value="Post"-->
</div>
</div>
</form>
</div>
</div>
</div>
</div>
you should be doing something like this in such situations .
In View Model:
this.changeBlock = function() {
$('#my-modal').modal('show');
}
function blockUser(post_id) {
//code here
}
this.Block=function(){
blockUser(this.postId);
if(this.block() != ""){
this.block("Blocked");
this.pointId(AS.currentUserDetails.name);
return "Blocked";}
}
}
this.Cancel=function(){
$('#my-modal').modal('hide'); //hide or close what ever suits
}
View :
<button id='block-confirm-button' data-bind="click:Blocked">Block</button>
<button id='block-cancel-button' data-bind="click:Cancel">Cancel</button>
Any issues on this lets us know

using modal as submit confirmation

I currently have a form. As per below.
<form action="/process" id="formTest" name="formTest" enctype="multipart/form-data" method="POST">
<input type="text">
</form>
I added a modal to confirm on the submit.
<div class="modal fade" id="bondModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title"></h4>
</div>
<div class="modal-body">
<p>Test;</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" id="accept" class="btn btn-primary">Accept</button>
</div>
</div><!-- /.modal-content -->
Now if the user submit, the modal of confirmation will be showed, and if the user subsequently choose accept, it will proceed the submit.
The problem is , the subsequent submit never works.
$('#formTest').submit(function(e) {
e.preventDefault();
$('#bondModal').modal('show');
$("#accept").click(function(e) {
$("#formTest").submit();
e.preventDefault();
$('#bondModal').modal('hide');
}
);
} });
The thing is if I change the code to reset instead of submit..it works for reset ..
$('#formTest').trigger('reset');
You've got yourself stuck in a loop.
When you fire the action:
$("#formTest").submit();
You are not submitting the form because you are calling your own function which prevents the default action:
$('#formTest').submit(function(e) {
e.preventDefault();
//do stuff
});
If you want to use the code you have currently you can do 1 of 2 things:
use one() on the submit function so it only fires once. This would require you to rebind on a reset or cancel
$('#formTest').one('submit', function(e) {
e.preventDefault();
//do stuff
});
Or unbind the submit function just before your forced submission.
$('#formTest').on('submit', function(e) {
e.preventDefault();
$("#accept").click(function(e) {
$('#formTest').unbind('submit');
$('#formTest').submit();
});
});
However, I would go a different way, and take the submit button out of the visible markup on the page. Just put an a tag in the form that you fire the open-modal function from upon click. Then you don't need to do any submission in your code, you just have the standard submit and reset buttons in the modal and they carry out their default behavior:
The markup:
<form>
<input type="text">
<a class="open-modal">Submit</a>
<div class="modal">
<h4 class="modal-title">Confirm?</h4>
<p>Test</p>
<input type="reset" class="btn btn-default">Cancel</button>
<input type="submit" class="btn btn-primary">Accept</button>
</div>
</form>
And the code:
$('a.open-modal').on('click', function(e) {
e.preventDefault();
$('.modal').fadeIn();
});
Much simpler. Hope this helps.
The issue is this line:
document.getElementbyname("formTest").submit();
There is no function called "getElementbyname()". It seems you are looking for document.getElementsByName() which returns a NodeList. In that case:
document.getElementsByName("formTest")[0].submit();
However, you can also use the document.forms array:
document.forms["formTest"].submit();
Finally, since your form has an ID, you could also use that:
document.getElementById("formTest").submit();

How to properly open and close Bootstrap modal from AngularJS

On my html page, I got just a simple Bootstrap modal and button to call it:
<button class="btn btn-primary" data-toggle="modal" data-target="#addUpdateGroup">Add group</button>
<div class="modal fade" id="addUpdateGroup" tabindex="-1" role="dialog" aria-labelledby="addUpdateGrouplLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
</div>
<form name="addUpdateGroupForm" ng-submit="addUpdateGroupForm.$valid && groupCtrl.addUpdateGroup()" novalidate>
<div class="modal-body">
<input type="hidden" ng-model="groupCtrl.group.id" name="groupid" />
<label for="groupname">Group name:</label>
<br>
<input ng-model="groupCtrl.group.name" type="text" name="groupname" id="groupname" required />
<br><br>
<label for="groupcolor">Boja grupe:</label>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Add</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</form>
</div>
</div>
</div>
It's a just simple form. The validation is done by AngularJS.
Now...when user submits the form, I'd like for the modal to close, but ONLY if it was valid input.
So I've put the code for closing the modal into the controller:
this.addUpdateGroup = function() {
// Adding a new group
if (typeof this.group.id === 'undefined') {
this.id += 1;
this.group.id = this.id;
this.groups.push(this.group);
// Updating an existing group
} else {
this.groups[this.group.id].name = this.group.name;
this.groups[this.group.id].color = this.group.color;
}
// Clean the form and remove the modal
this.group = {};
$scope.addUpdateGroupForm.$setPristine(true);
$('.modal').modal('hide');
};
But this doesn't follow the best practice of not manipulating the DOM from the controller.
QUESTION: Is there a better way? How would you implement a modal which needs to be shown or hidden when certain function in controller is called?
You are not following Angular best practices. If you havent done so already, review this legendary answer: https://stackoverflow.com/a/15012542/202913 Specifically points 1 - 3 of that post.
That out of the way, you should be using either of the following two libraries. Both of them implement Bootstrap's functionality, but with a native Angular implementation, i.e. it does not rely on the Javascript library of Bootstrap (but does use the Bootstrap's CSS):
angular-ui/bootstrap
angular-strap
Both are excellent, so use whichever library feels more comfortable to your coding style.

Categories

Resources