I am creating my custom form-edit-account.php template. This contains a form that allows users to change their name, surname, password and other info. Originally the form does not perform ajax requests, you click the save changes button, the data is saved and the page is reloaded. The required fields and their validity are managed by the file https://woocommerce.github.io/code-reference/files/woocommerce-includes-class-wc-form-handler.html#source-view.218
What I did was create ajax request for the form in order to save the fields without the page refresh. The fields are edited and updated correctly, so it works. However, handling validation not working.
Somehow I need field handling validation but I don't know how to proceed I'm stuck at this point. I have two ideas I could work on:
Try somehow to make the original handling validation work.
Create a custom handling validation with js or php separately from the original file, but I don't know if this is correct.
How could I handle field validation? I hope someone can help me understand how I could do this, I appreciate any help and thank you for any replies.
Example of 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' );?> >
<!-- 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>
Js File
jQuery(document).ready(function($) {
$('.mts-edit-account').on('submit', function(e) { //form onsubmit ecent
e.preventDefault(); // the preventDefault function stop default form action
//Ajax function
jQuery.ajax({
type: "post",
data: jQuery(".mts-edit-account").serialize(),
url: "wp-admin/admin-ajax.php",
success: function(data) {
alert('Form Inviato');
}
});
});
});
functions.php
add_action( 'wp_ajax_save_account_details', 'save_account_details' );
add_action( 'wp_ajax_nopriv_save_account_details', 'save_account_details' );
add_action('woocommerce_save_account_details_errors','save_account_details', 10, 1 );
function save_account_details() {
// A default response holder, which will have data for sending back to our js file
$response = array(
'error' => false,
);
// Example for creating an response with error information (This not working)
if (trim($_POST['account_first_name']) == '') {
$response['error'] = true;
$response['error_message'] = 'Name is required';
if (trim($_POST['account_first_name']) == '') {
$response['status'] = false;
$response['message'] = 'Name is required';
}else{
$response['status'] = true;
$response['message'] = 'success';
}
// Exit here, for not processing further because of the error
echo json_encode($response);
exit();
}
exit(json_encode($response));
}
Thanks to the intervention of Martin Mirchev in the comments I was able to solve the problem.Here is the solution for anyone who is in the same conditions.
(The form remained the same)
Js File
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('.woocommerce-notices-wrapper').append(response);
jQuery('.woocommerce-notices-wrapper').prepend(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();
} else {
$response = "Settings Saved!";
}
// Don't forget to exit at the end of processing
echo json_encode($response);
exit();
}
Related
First, please look at https://staging.upstatetoday.com/letmein
I have inherited a very old log in mechanism that has begun to not work lately - Firefox refuses to log users in, other browsers can be iffy, too. The site is wordpress, but the login is a different server (paywall).
Correct behavior is: insert username and password, click login button, page refreshes and sends user to the homepage if authentication is valid; alert drops that the username/password is incorrect if invalid.
This only seems to happen corectly in Chrome on the desktop, and sometimes in Edge. Firefox just refreshes the page. There are no js errors.
The login button is supposed to call a JS function that stores the current url (not needed in this implementation) then calls a function (in the wordpress functions.php file) that queries a separate site with the username and password and receives an XML response. That response is evaluated for a Yes and the user is allowed in or not, based on that xml response. If the user is allowed, the JS function returns the user to the page where they last were. If they are not allowed, the JS function alerts with bad user or pass msg.
Anyone can go to any post or page, but the single.php template is modified to check for authentication. If they are authenticated, they see the post. If not, they see a notice to subscribe or log in.
But, There's more going on in the code that is not needed (?) and I think there is unnecessary duplication of the process.
You can see the dialog at the link on top. Please ignore the styling (coming later).
I have moved code, tried snippets, php sessions, but nothing is working in Firefox at all, and with no error messages, I do not know how to proceed.
This is the code for the login dialog:
<?php if(!isset($_SESSION['auth']) ) { ?>
Forgot user name/password? Click Here
<form>
<div class="form-group">
<label for="pwd">User name:</label>
<input type="text" autocomplete="user-name" class="form-control" id="user-name" placeholder="Enter user name" style="width:200px; margin-bottom:5px;"/></div>
<div class="form-group">
<label for="pwd">Password:</label>
<input type="password" autocomplete="current-password" class="form-control" id="pwd" placeholder="Enter password" style="width: 200px;margin-bottom:5px;"/> <button type="submit" class="btn btn-primary" id="sub-sign-in" style="color:blue;font-size:1.0em">Log in to Upstate Today</button> </div>
</form>
<button class="btn btn-default">Register or Renew Subscription </button>
<?php } else { ?>
"<script type="text/javascript">
function Redirect()
{
window.location="https://staging.upstatetoday.com";
}
document.write("You will be redirected to the homepage in 5 seconds");
setTimeout('Redirect()', 5000);
</script>"
<?php } ?>
This is the js that is called by "sub-sign-in" :
jQuery(document).ready(function( $ ){
var pageURL = $(location).attr("href");
localStorage.setItem("page_url", pageURL);
console.log('ready');
$('#sub-sign-in').click(function(){
console.log('enter');
var user_name=$('#user-name').val();
var password=$('#pwd').val();
$.ajax({
type: "POST",
url: '/wp-admin/admin-ajax.php',
data: ({
action: "check_address",
name: user_name,
pass:password
}),
success: function (response){
console.log(response);
var pg_url = localStorage.getItem("page_url");
if(response == 'Yes0'){
window.location.replace(pg_url);
}
else{
alert('wrong username or password');
}
},
error: function(error){
console.log(error);
}
});
});
});
This is the code from the child theme functions.php
function register_my_session()
{
if( !session_id() )
{
session_start();
}
}
add_action('init', 'register_my_session');
/* session_write_close(); */
function check_address()
{
$name = $_POST["name"];
$password = $_POST["pass"];
/*$edition = $_POST["edition"];
$subdate = $_POST["subscriptiondate"]*/
$response = wp_remote_get( 'https://seneca.newzware.com/authentication/auth70_xml.jsp?site=seneca&login_id='.$name.'&password='.$password);
$xml = simplexml_load_string($response['body']);
$isValid = (string) $xml->authenticated;
if(!session_id()) {
session_start();
}
if($isValid == 'Yes'){
$_SESSION['auth'] = '1';
}
echo $isValid;
}
add_action( 'wp_ajax_check_address', 'check_address' );
add_action( 'wp_ajax_nopriv_check_address', 'check_address' );
add_action( 'wp_enqueue_scripts', 'hello_elementor_child_enqueue_scripts', 20 );
function wpb_widgets_init() {
register_sidebar( array(
'name' => 'Custom Header Widget Area',
'id' => 'newzware-widget',
'before_widget' => '<div class="newzware-widget">',
'after_widget' => '</div>',
'before_title' => '<h2 class="newzware-title">',
'after_title' => '</h2>',
) );
}
add_action( 'widgets_init', 'wpb_widgets_init' );
This is the single post content that includes whether the user can read that post or not (ie, is authenticated):
<?php
/**
* The template for displaying singular post-types: posts, pages and user-defined custom post types.
*
* #package HelloElementor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
?>
<?php
while ( have_posts() ) :
the_post();
?>
<main id="content" <?php post_class( 'site-main' ); ?> role="main">
<?php if ( apply_filters( 'hello_elementor_page_title', true ) ) : ?>
<header class="page-header">
<?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
</header>
<?php endif; ?>
<!-- Newzware Protection Code -->
<?php
$key = 'Free Story';
$themeta = get_post_meta($post->ID, $key, TRUE);
if($themeta != '') {
$free_story = 1;
}
?>
<?php if($_SESSION['auth'] == '1' OR current_user_can( 'read_post' ) OR $free_story == '1' ) { ?>
<!-- end part 1Newzware Protection Code -->
<div class="page-content">
<?php the_content(); ?>
<!-- beginpart 2 Newzware Protection Code -->
<?php } else { ?>
<div class='ifsub-panel'> <div class='ifsubpanel-heading' style='background:#2318A4; color:#fff; text-align:center;'><b>Subscribe To The Journal</b></div><div class='ifsubpanel-body'> <p style='text-align:center'>
If you are already registered with UpstateToday.com, please click the LOGIN button in the upper left corner of this window to log in and continue reading.<br><br>
If you'd like to subscribe,<br>
Please click here for options. We'd love for you to join our family.</b></p>
</div></div>
<?php } ?>
<!-- End Newzware Protection Code -->
<div class="post-tags">
<?php the_tags( '<span class="tag-links">' . __( 'Tagged ', 'hello-elementor' ), null, '</span>' ); ?>
</div>
<?php wp_link_pages(); ?>
</div>
<?php comments_template(); ?>
</main>
<?php
endwhile;
I want to make this work reliably in desktop and mobile browsers. I'd love to have a user tap a login button, go to a page with the dialog, log in, then return to the home page.
Thanks for your time and pointers.
I'm checking this form for errors using PHP code which is on the same index.php file:
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="POST">
<?php if(!empty($formErrors)){ ?>
<div id="errors">
<?php
foreach($formErrors as $error)
{ echo '* ' . $error . '.<br/>';}
?>
</div>
<?php } ?>
<input type="text" name="firstname">
<input type="submit" value="send">
</form>
The PHP code is as follows:
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$fname = $_POST['firstname'];
$formErrors = array();
if(strlen($fname) < 2 ){
$formErrors[] = "First name must be longer than 1 character";
}
}
?>
Everything is working fine up to this point, except that I want to prevent the page from scrolling to the top upon form submission. Therefore i used ajax to solve this problem:
$("form").submit(function(e){
e.preventDefault();
$.ajax({
type: $(this).attr("method"),
url: $(this).attr("action"),
data: $(this).serialize()
});
});
Now the form errors won't display anymore, which is not what I want. How can I show the errors again while not discarding ajax? Thanks.
Although this isn't the best way, you can echo the JSON from the file and display those errors in your ajax function like below:
FrontEnd(ajax):
$("form").submit(function(e){
e.preventDefault();
$.ajax({
type: $(this).attr("method"),
url: $(this).attr("action"),
data: $(this).serialize() + '&ajax=1',
dataType:'json',
success: function(res){
if(res.success === false){
$('#errors').html('<ul><li>' + res.errors.join('</li><li>') + '</li></ul>');
}else{
$('#errors').html('');
}
}
});
});
Backend:
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$fname = $_POST['firstname'];
$formErrors = array();
if(strlen($fname) < 2 ){
$formErrors[] = "First name must be longer than 1 character";
}
// add this additional check
if(($_POST['ajax'] ?? 'N/A') == '1'){
echo json_encode(['success' => false,'errors' => $formErrors]);
exit; // since we will only send the JSON back to the browser, not the entire form
}
}
?>
Change your form code to this(adding a errors div always by default):
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="POST">
<div id="errors"></div>
<input type="text" name="firstname">
<input type="submit" value="send">
</form>
I trying to make opening WP posts in popup.
Firts part of code its form in posts loop where I get query of posts what should be opened
<form id="postForm" method="POST">
<input id="postQuery" style="display: none" name="postQuery" value="<?php echo get_the_ID() ?>">
<input id="sendQueryBtn" data-toggle="modal" data-target="#exampleModalLong" type="submit" value="<?php the_title(); ?>">
</form>
Next is my JS, where I do query check by alert
$(document).ready(function () {
$("form").submit(function () {
let xuinya = $(this).serialize();
$.ajax({
type: "POST",
url: '.../footer.php',
data: xuinya,
success: function (data) {
alert(xuinya)
},
error: function (jqXHR, text, error) {
$('#modalBody').html(error);
}
});
return false;
});});
And I final, here is part of HTML with modal, where I try to use POST
<div id="modalBody" class="modal-body">
<?php
echo $_POST["postQuery"];
echo apply_filters( 'the_content', get_post( $_POST["postQuery"] )->post_content );
?>
</div>
My problem is because when I check query in JS - qet alert message with correct value, but in php I always qet simple "1".
I don't get why you posting to footer.php, I think its should be admin-ajax.php
just simply add to youfooter.php
<script>
var ajax_url = "<?php echo admin_url( 'admin-ajax.php' ); ?>";
</script>
Change url value in js to ajax_url, make sure hat with data you posting variable action and then create function in functions.php, something like this(if you sending action value as 'get_pop_posts')
add_action( 'wp_ajax_get_pop_posts', 'get_pop_posts_init' );
add_action( 'wp_ajax_nopriv_get_pop_posts', 'get_pop_posts_init' );
function get_pop_posts_init() {
$data = $_POST;
print_r($data);
die();
}
I try to prepare simple contact form with jquery, ajax and php without refresh. Everything works fine besides event.preventDefault();
That's my files:
contact_engine.php
<?php
$name = $_POST['name'];
...
$from = 'from';
$to = 'to';
$subject = 'subject';
$human = '4';
$body = ".........";
if ($_POST['submit'] && $human == '4') {
if (mail ($to, $subject, $body, $from)) {
echo '<p>Thanks</p>';
} else {
echo '<p>Error</p>';
}
} else if ($_POST['submit'] && $human != '4') {
echo '<p>You answered the anti-spam question incorrectly!</p>';
}
?>
Ajax/jQuery
$('form').on('submit', function(event){
event.preventDefault();
$.ajax('.../contact_engine.php', {
type: 'POST',
data: $('form').serialize(),
success: function(result) {
}
});
});
PHP
<form method="post" action="<?php bloginfo('template_directory'); ?>/contact_engine.php">
<div class="box">
<input type="text" name="name" class="pola formbg name" placeholder="Name" />
.
.
.
.
<p><input id="form-button" type="submit" name="submit" value="Send" /></p>
</div>
<br style="clear: left;" />
</form>
When I remove event.preventDefault(); everything is ok, I receive a message from form but site are refreshing and I see 'thanks' message.
I used Wordpress as you probably seen.
Yeah, in this kind of instance why have a form/submit button.
Remove the form and change the input from a submit button to a standard button.
Put the function on the button, job done.
$('#form-button').on('click', function(event){
$.ajax('.../contact_engine.php', {
type: 'POST',
data: $('form').serialize(),
success: function(result) {
//do something with the return code
}
});
});
Give your form an ID - I think the problem is your submit handler does is not firing:
$( "#myForm" ).submit(function( event ) {...
and then change your jQuery to read:
$( "#myForm" ).submit(function( event ) {
event.preventDefault();
...
See http://api.jquery.com/jquery.post/
I'm new to ajax concept. Here i'm trying to insert the user details(signup form) into the database. it inserted the datas into the db succesfully. But, ajax is my problem.
1) i didn't get any error message if form fields are empty. you can see my below codes i've done validation on post.php page. but, it doesn't return the error values. 2) it stores the empty values into database. 3) if datas stored successfully i want to get the success message & if datas failed to store in db i want to get the error message. How should i do these all things?
Ajax.js
$(function () {
$('form').on('submit', function (e) {
$.ajax({
type: 'POST',
url: 'post.php',
data: $('form').serialize(),
success: function(msg) {
if(msg=='error_n')
{
$("#e_name").html('Name required');
}
if(msg=='error_m')
{
$("#e_mobile").html('Mobile required');
}
//success and error alert
if(data="inserted")
{
alert("insertion success");
}
else
{
alert("falid to insert into database");
}
}
});
e.preventDefault();
});
});
Post.php
<?php
include_once('config.php');
$name = trim($_POST["name"]);
$mobile = trim($_POST["mobile"]);
if($name == "")
{
echo 'error_n';
}
if($mobile == "")
{
echo 'error_m';
}
try
{
$stmt = $conn->prepare("INSERT INTO sample ( Name, Mobile ) VALUES ( ?, ? )");
$conn->errorInfo();
$stmt->bindParam('1', $name, PDO::PARAM_STR);
$stmt->bindParam('2', $mobile, PDO::PARAM_STR);
$stmt->execute();
}
catch(PDOException $e)
{
'Query failed to insert into database' .$e->getMEssage();
}
?>
Homepage.php
<p>register here</p>
<div id="light" class="white_content">
Close
<form>
<input type="hidden" name="form" value="values" />
name : <input name="name" id="name" type="text" /><span id="e_name"></span> <br />
mobile : <input name="mobile" id="mobile" type="text" /><span id="e_mobile"></span> <br />
<input type="submit" value="submit" />
</form>
</div>
<div id="fade" class="black_overlay"></div>
After your error messages are returned, you need to stop the script execution. Your current code still tries to add the values and hence overrides your custom error messages. Most probably then your PHP returns your exception message and which is not what your JavaScript is expecting.
if($name == "")
{
echo 'error_n';
die(); // Stop here
}
if($mobile == "")
{
echo 'error_m';
die(); // Stop here
}
Also add echo 'inserted'; when your database insert is successful.