How to refresh div after ajax success response - javascript

I have a form with ajax requests, when the fields are not respected and click on submit button the messages are displayed without page refresh. This works, the problem is that if the form is submitted several times, the error messages accumulate and multiple messages are displayed at the same time.
For example: if you leave field name blank and then submit, the error message (field required) appears. When you enter your name and then submit the success message (Settings Saved) appears but the error message is still visible.
What I want to get is only one message at a time, so the div should update showing the new message and deleting the previous one.
Now, I've tried doing some research and I understand that an if condition with $("#my-div").load("#my-div"); can be used in these cases but i have no idea how to do it, i am new to all this.
Can anyone help me understand how to achieve this? I appreciate any help and thank you for any replies.
My form
<form name="Form" class="mts-edit-account" action="<?php echo admin_url('admin-ajax.php'); ?>" method="post" enctype="multipart/form-data" <?php add_action( 'woocommerce_edit_account_form_tag', 'action_woocommerce_edit_account_form_tag' );?> >
<!-- Message section -->
<div class="msg_box"></div>
<!-- Fist & Last Name Field -->
<div class="row name_surname">
<div class="form-row">
<label class="t3" for="account_first_name">Nome *</label>
<input type="text" placeholder="Inserisci il tuo nome" class="field-settings" name="account_first_name" id="account_first_name" value="<?php echo esc_attr( $user->first_name ); ?>" />
</div>
<div class="form-row">
<label class="t3" for="account_last_name">Cognome *</label>
<input type="text" placeholder="Inserisci il tuo cognome" class="field-settings" name="account_last_name" id="account_last_name" value="<?php echo esc_attr( $user->last_name ); ?>" />
</div>
<!-- Save Settings -->
<p style="margin-bottom: 0px!important;">
<?php wp_nonce_field( 'save_account_details', 'save-account-details-nonce' ); ?>
<button type="submit" class="edit-account-button" name="save_account_details" value="<?php esc_attr_e( 'Save changes', 'woocommerce' ); ?>"><?php esc_html_e( 'Salva modifiche', 'woocommerce' ); ?></button>
<input type="hidden" name="action" value="save_account_details" />
</p>
</div>
</form>
Script
jQuery(document).ready(function($) {
$('.mts-edit-account').on('submit', function(e) {
e.preventDefault();
//Ajax function
jQuery.ajax({
type: "post",
data: jQuery(".mts-edit-account").serialize(),
url: "wp-admin/admin-ajax.php",
success : function( response ) {
jQuery('.msg_box').append(response);
}
});
});
});
Functions.php
add_action( 'wp_ajax_save_account_details', 'save_account_details' );
add_action( 'woocommerce_save_account_details_errors','save_account_details', 10, 1 );
function save_account_details() {
if (trim($_POST['account_first_name']) == '') {
$response = wc_print_notices( $return = false );
} else {
$response = "Settings Saved!";
}
// Don't forget to exit at the end of processing
echo json_encode($response);
exit();
}

You've used jQuery('.msg_box').append(response) method for displaying the messages. The documentation clearly states that this is used to insert content, specified by the parameter, to the end of each element in the set of matched elements.
Naturally giving you the multiple messages. If you just need a single message, then use:
jQuery('.msg_box').html(response)
.html() will ensure that the content of the container is overridden each time.
Reference: Official Documentation

Related

Woocommerce - wc_print_notices returns two messages instead of one, what's wrong?

I'm editing woocommerce form-edit-account.php, in this template there is a form that allows users to change name, surname, address etc. I added ajax requests to save the data without reloading the page. The data is saved correctly, so the ajax request works fine. The only step I can't get to work properly are handling error messages.
The problem
when click on submit button and the data is saved successfully, two messages appear.
The first message is the original woocommerce message: "Account details changed successfully", and can be found at https://woocommerce.github.io/code-reference/files/woocommerce-includes-class-wc-form-handler.html#source-view.346. The second message is what I wrote in my functions.php with wc_add_notice.
Expectations
I should only get the message I added to functions.php with wc_add_notice, why am I getting the original message as well? What am I doing wrong ?
Hope someone can help me with this, I can't figure out where the mistake is. I appreciate any help and thank you for any replies.
Js which handles updating fields and error / success message
$(document).ready(function($) {
$('.mts-edit-account').on('submit', function(e) {
e.preventDefault();
//Ajax Handling Error msg
var $form = $(this);
$.post(
$form.attr('action'),
$form.serialize(),
function(data) {
$('.newdiv').html(data);
}, 'json'
);
//Ajax Save settings
$.ajax({
type: "POST",
data: $(".mts-edit-account").serialize(),
beforeSend: function() {
$(".container_loader").show();
},
success: function(data) {
$(".container_loader").hide();
}
});
});
});
Handling error in functions.php
// Validate - my account
add_action( 'woocommerce_save_account_details_errors', array( &$user, 'save_account_details' ), 10, 1);
add_action( 'wp_ajax_save_account_details', 'save_account_details' );
function save_account_details( &$user ) {
if (isset( $_POST['account_first_name'] ) == '') {
wc_add_notice("<b>Nome</b> รจ un campo obbligatorio", "error");
$response = wc_print_notices(true);
} else if (isset($_POST['account_first_name']) ) {
wc_add_notice("Modifiche salvate con successo", "success");
$response = wc_print_notices(true);
}
echo json_encode($response);
exit();
}
Example of my form html
<form name="Form" class="mts-edit-account" method="post" action="<?php echo admin_url('admin-ajax.php'); ?>" enctype="multipart/form-data" <?php add_action( 'woocommerce_edit_account_form_tag', 'action_woocommerce_edit_account_form_tag' );?> >
<?php do_action( 'woocommerce_edit_account_form_start' ); ?>
<!-- Fist & Last Name Field -->
<div class="row name_surname">
<div class="form-row">
<label class="t3" for="account_first_name">Nome *</label>
<input type="text" placeholder="Inserisci il tuo nome" class="field-settings" name="account_first_name" id="account_first_name" value="<?php echo esc_attr( $user->first_name ); ?>" />
</div>
<div class="form-row">
<label class="t3" for="account_last_name">Cognome *</label>
<input type="text" placeholder="Inserisci il tuo cognome" class="field-settings" name="account_last_name" id="account_last_name" value="<?php echo esc_attr( $user->last_name ); ?>" />
</div>
</div>
<!-- Other fields -->
<!-- Save Info Settings -->
<div style="margin-bottom: 0px!important;">
<?php wp_nonce_field( 'save_account_details', 'save-account-details-nonce' ); ?>
<button type="submit" class="edit-account-button" name="save_account_details" value="<?php esc_attr_e( 'Save changes', 'woocommerce' ); ?>"><?php esc_html_e( 'Salva modifiche', 'woocommerce' ); ?></button>
<input type="hidden" name="action" value="save_account_details" />
</div>
</form>

Prevent (non-bootstrap) Modal Popup from immediately closing after button submit, and display messages

I have created a modal popup to login (and also retrieve password) picking on some hints from other posts. It works fine except that when I submit the login button it immediately closes the modal, even if there is a message displayed. One can see that the message was displayed by opening the popup again:
The intention is obviously not to have the popup close immediately when there is any kind of message, otherwise the client doesn't have the chance to see it.
I have searched for this problem in this website and others but only saw solutions that seem to imply bootstrap modals and other solutions that do not fit my case. Any help is highly appreciated.
My code below:
//JAVASCRIPT
// Get the modal
var modal2 = document.getElementById('myModal2');
// Get the button that opens the modal
var btn2 = document.getElementById("myBtn_login_popup");
// Get the <span> element that closes the modal
var span2 = document.getElementsByClassName("close2")[0];
var pasw = document.getElementById("retrieve_pasw");
var pasw_form = document.getElementById("modal-body_b");
// When the user clicks on the button, open the modal
if (btn2) {
btn2.onclick = function() {
modal2.style.display = "block";
}
}
// When the user clicks on <span> (x), close the modal
span2.onclick = function(event) {
modal2.style.display = "none";
}
pasw.onclick = function(event) {
pasw_form.style.display = "block";
}
<!-- HTML
<!-- The Modal -->
<div id="myModal2" class="modal">
<!-- Modal content -->
<div class="modal-content2">
<div class="modal-header_a">
<?php echo '<h2>' . $header_content . '</h2>';?>
<span class="close2"></span>
</div>
<?php wc_print_notices(); ?>
<div class="modal-body_a">
<form action="" class="woocommerce-form woocommerce-form-login login" method="post">
<?php echo __('Please insert your username/email and your password to login:', 'woocommerce_php'); ?>
<?php do_action( 'woocommerce_login_form_start' ); ?>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide"
<label for="username"><?php _e( 'Username or email address', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="username" id="username"
value="<?php echo ( ! empty( $_POST['username'] ) ) ? esc_attr( $_POST['username'] ) : ''; ?>" autofocus required />
</p>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="password"><?php _e( 'Password', 'woocommerce' ); ?> <span class="required">*</span></label>
<input class="woocommerce-Input woocommerce-Input--text input-text" type="password" name="password" id="password" required />
</p>
<?php do_action( 'woocommerce_login_form' ); ?>
<p class="form-row">
<?php wp_nonce_field( 'woocommerce-login', 'woocommerce-login-nonce' ); ?>
<input type="submit" class="woocommerce-Button button" name="login" value="<?php esc_attr_e( 'Login', 'woocommerce' ); ?>" />
<label class="woocommerce-form__label woocommerce-form__label-for-checkbox inline">
<input class="woocommerce-form__input woocommerce-form__input-checkbox" name="rememberme" type="checkbox" id="rememberme" value="forever" />
<span><?php _e( 'Remember me', 'woocommerce' ); ?></span>
</label>
</p>
<p class="woocommerce-LostPassword lost_password">
<button type="button" id="retrieve_pasw" class="retrieve_pasw" href=""><?php _e( 'Forgot password?', 'woocommerce' ); ?></button>
</p>
<?php do_action( 'woocommerce_login_form_end' ); ?>
</form>
</div>
</div>
</div>
Well I got it !! After looking a lot around and thinking about it.
First we must include a variable to check whether there are (error) messages in the buffer to be displayed. If so, then just let them print to screen and force the reopening of the modal.
So in the first step, it will suffice to replace the line where I had
<?php wc_print_notices(); ?>
with the following php:
<?php
ob_start();
wc_print_notices();
$messages = ob_get_contents();
?>
The second step implies some javascript to make sure that when the variable $messages is not empty, we force the modal to stay open.
var messages_bool = "<?php echo !empty($messages); ?>";
if (messages_bool) {
modal2.style.display = "block";
}
Finally, we must make sure that if the user closes the modal and then reopens it, that the message is no longer there ...
var elements = document.getElementsByClassName("woocommerce-error");
for(var i = 0, length = elements.length; i < length; i++) {
elements[i].style.display = 'none';
}
This is working fine in my website.

Form check information & insert on same page

So I've got a regular form
<form action="includes/send.php" method="post" onsubmit="return isValidForm()" />>
<h1>Opgeven workshops</h1>
<label for="name">Voornaam:</label>
<input type="text" autocomplete="off" id="name" name="firstname">
<label class="choice" data-id="1"><input type="checkbox" name="group1" value="use your apple1">use your apple<span class="left" ></span>
</label>---more stuff more stuff more stuff--
Now I submit the form I want to show the information the user filled in in the form like this
$f_name = $_POST['firstname'];
$l_name = $_POST['lastname'];
U hebt zich ingeschreven bij: <br />
Eerste workshop : <?php echo $first; ?><br />
Tweede workshop : <?php echo $second; ?><br />
Klopt dit?
<button type="submit" onclick="send()">Ja</button>
<button type="submit" onclick="noSend()">nee</button>
and when the user clicks on send it sends the information from the previous form to the query to insert it into the database. I'm trying to do this without having to make another 'hidden form' which submits it again because it is unnecessary code when you can just let the script 'wait' and continue with the script / insert functionallity when the button is pressed.
I tried setting a variable $submit= false; and inside the send function (which is in javascript) set submit to true but that doesn't seem to work because it automatically sets the variable to true without pressing the button.
function send(){
<?php $submit = true ?>
var submit = <?php echo $submit ?>;
console.log(submit);
}
if($submit){
echo 'submitted';
} else {
echo 'not true';
}
On your php side pass the values when calling your Javascript 'send()' function
<?php
$first = "First course";
$second = "Second course";
?>
U hebt zich ingeschreven bij: <br />
Eerste workshop : <?php echo $first; ?><br />
Tweede workshop : <?php echo $second; ?><br />
Klopt dit?
<!-- pass the required values into the function, this is just a basic implementation you could also use a loop to fill in the values -->
<button type="button" onclick="send(true, '<?php echo $first ?>', '<?php echo $second ?>')">
Ja
</button>
<button type="button" onclick="send(false)">
nee
</button>
For the receiving function you could implement something like this
<script type="text/javascript">
function send(submit){
//Get all arguments passed except the first variable, the submit boolean
var listOfVariablesToPost = Array.prototype.slice.call(arguments,1);
if(submit){
console.log("post");
console.log(listOfVariablesToPost);
/* Do POST here either by using XMLHttpRequest or jQuery AJAX/POST (Or any other way you like)*/
/* XMLHttpRequest: http://stackoverflow.com/questions/9713058/sending-post-data-with-a-xmlhttprequest */
/* jQuery POST https://api.jquery.com/jquery.post/ */
}else{
console.log("No post")
/* Don't post and do whatever you need to do otherwise */
}
}
</script>
This is a very simple implementation, but I hope it helps.

Jquery UI Dialog working just once?

As I said on my previous post, I have this bit of php code:
EDIT: I pasted the wrong code, corrected.
<?php
$posts = new Posts();
foreach($posts->getPosts() as $post){ ?>
<div class="post">
<h3><a class="post-link" data-post-id="<?php echo $post['id']; ?>" href="javascript:void(0)"><?php echo $post['title']; ?></a></h3>
</div>
<?php } ?>
<div id="insert-answer" title="Add new idea to post">
<form id="myForm" action="insertidea.php" method="post">
<fieldset>
<p><label for="idea">Your idea:</label>
<input type="text" name="idea" class="idea"</p>
<p><label for="pic">Have a pic? Paste its URL here! (optional)</label>
<input type="text" name="pic" class="pic"></p>
<input type="hidden"class="author" name="author" value="<?php echo $_SESSION['google_data']['id']; ?>" />
<input type="hidden"class="forpost" name="forpost" value="<?php echo $post['id']; ?>" />
</fieldset>
</form>
And I have a form that pops up from each post's link:
$( "#insert-answer" ).dialog({
autoOpen: false,
modal:true,
buttons: {
"Add idea": function() {
var forpost = $("#insert-answer").data("post-id"),
author = $("#author").val(),
idea = $(".idea").val(),
pic = $(".pic").val();
$.post('insertidea.php',{
forpost: forpost, author: author, idea: idea, pic: pic, action:'joined'
});//End Post
$("#insert-answer").val('');
$(".pic").val('');
$(this).dialog("close");
},
Cancel: function() {
$( this ).dialog( "close" );
}
}
});
$( ".post-link" ).on('click', function() {
var postid = $(this).data("post-id");
var answer = $("#insert-answer");
$(answer).data('post-id', postid);
$(answer).dialog( "open" );
});
So the user is supposed to be presented with a list of post, each post has a link that pops up the dialog that in turn contains a form that sends data to a mysql database trough another php file via post and it works fine, just only the first time. The second time I get some syntax errors and according to firebug, it comes from the array that is sent to the php file. I'm suspecting my dialog function is incomplete, do I need to "unset" anything after the data is sent? How would I accomplish that?
Thanks a lot!

how can I put validation_errors() at the right side of textfield?

I have followed the learning tutorials in CodeIgniter and Im currently creating a program using the same procedure on my reference(link posted below) where there is a log-in form. I have no problem with the functions, I just want to put the validation_errors() at the right side of the textfield where if the username is empty or incorrect, the error message will display on the right side of the textfield. Is there a way to do this? or should I use javascript instead of using this validation_errors()? Hope someone will help me. Thanks!
Here's the code in VIEW:
<h3>Log-In with CodeIgniter</h3>
<?php echo validation_errors(); ?>
<?php echo form_open('verifylogin'); ?>
<label for="username">Username:</label>
<input type="text" size="20" id="username" name="username"/>
<br/>
<label for="password">Password:</label>
<input type="password" size="20" id="password" name="password"/>
<br/>
<input type="submit" value="Log-In"/>
</form>
Here's the code in CONTROLLER:
function index() {
$this->load->library('form_validation');
$this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean');
$this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean|callback_check_database');
if($this->form_validation->run()==FALSE) {
$this->load->view('login_view');
}
else {
redirect('home', 'refresh');
}
}
function check_database($password) {
$username=$this->input->post('username');
$result=$this->user->login($username, $password);
if($result) {
$sess_array=array();
foreach($result as $row) {
$sess_array=array('id'=>$row->id, 'username'=>$row->username);
$this->session->set_userdata('logged_in', $sess_array);
}
return TRUE;
}
else {
$this->form_validation->set_message('check_database', 'Invalid username or password');
return FALSE;
}
}
Reference: http://www.codefactorycr.com/login-with-codeigniter-php.html
<h3>Log-In with CodeIgniter</h3>
<?php if (form_error('password')=="Invalid username or password")
{
echo form_error('password');
}
?>
<?php echo form_open('verifylogin'); ?>
<label for="username">Username:</label>
<input type="text" size="20" id="username" name="username"/><?php echo form_error('username'); ?>
<br/>
<label for="password">Password:</label>
<input type="password" size="20" id="password" name="password"/><?php echo form_error('password'); ?>
<br/>
<input type="submit" value="Log-In"/>
</form>
<?php echo form_open('verifylogin'); ?>
This will display all the errors of FORM at one time - they come in form of bulk errors (not splitted)
<?php echo form_error('username'); ?>
<?php echo form_error('password'); ?>
This is the right way of displaying the individual errors , where CodeIgniter provides you the way of displaying the error individually
showing individual errors in codeigniter
and search for Showing Errors Individually
You can display them in span tag at side of input fields - to get the kind of O/P which you want
Here's what I did..
$this->form_validation->set_message('check_database', '<br/><br/>Invalid username or password');
I added <br/> to Invalid username or password so that it will not place to password field.

Categories