Yii Framework Forum: Stop multiple form submissions - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • This topic is locked

Stop multiple form submissions Rate Topic: -----

#1 User is offline   chamalsl 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 15
  • Joined: 13-November 09

Posted 30 December 2009 - 10:56 AM

Hi,

Is there a YII specific method to stop multiple form submissions (Ex. User double clicking on submit button).

Thanks,
Chamal.
0

#2 User is offline   Mike 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 3,013
  • Joined: 06-October 08
  • Location:Upper Palatinate

Posted 30 December 2009 - 12:35 PM

After you processed the form use $this->refresh() to reload the current page or $this->redirect() to load another page.
0

#3 User is offline   rfenner 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 35
  • Joined: 10-March 09

Posted 01 January 2010 - 02:53 PM

View PostMike, on 30 December 2009 - 12:35 PM, said:

After you processed the form use $this->refresh() to reload the current page or $this->redirect() to load another page.

I think he was talking about after the user clicks submit but before the form is processed.

You change the action on the submit button so that when the user clicks it that it disables itself and then submits the form you'll probably want to run your client side form validation first before disabling the button. As for a Yii specific method their isn't one specifically that sets it up easily for you. However you can add to the beginform some html options to change the action of the form. something like
CHtml::beginform('yoururl', 'POST', array('onClick'=>'this.disabled=true;this.form.submit();');

0

#4 User is offline   makro 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 71
  • Joined: 05-November 09
  • Location:Novara, IT

Posted 09 January 2010 - 05:52 AM

I think it could be a better solution put the code below into main.php layout file

$cs=Yii::app()->clientScript;
$cs->registerScript('submit','
$(":submit").click(function() {
	$(this).attr("disabled",true);
})',CClientScript::POS_READY);


EDIT: This doesn't work on IE (as usual...) so forget it

EDIT (again): This should work on IE too

$cs=Yii::app()->clientScript;
$cs->registerScript('submit','
$(":submit").mouseup(function() {
	$(this).attr("disabled",true);
	$(this).parents("form").submit();
})',CClientScript::POS_READY);

0

#5 User is offline   iGrog 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 64
  • Joined: 09-October 09

Posted 23 January 2010 - 10:47 AM

How I can send with POST request 'submit's button value.
E.g. <input type='submit' name='doAction' value='Send' />

in Controller I need to check:

if(!empty($_POST["MyModel"]) && isset($_POST["doAction"]))
{
    $model->attributes = $_POST["MyModel"];
}


But it doesn't work, cos submit not exists in POST query.
0

#6 User is offline   Mike 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 3,013
  • Joined: 06-October 08
  • Location:Upper Palatinate

Posted 24 January 2010 - 07:43 AM

Check the output of print_r($_POST). The submit button must appear. Why do you want to check it anyway? isset($_POST['MyModel']) is sufficient to find out, wether your form was submitted.
0

#7 User is offline   Dan Gibas 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 10
  • Joined: 21-October 10
  • Location:Gibraltar

Posted 01 December 2010 - 10:36 AM

I added a dynamic $formToken hidden field to every form then when form is submitted save the token to session. You can then check against this and take it from there...

This method works well, I can post code if needed :)
Dan Gibas,
HYGEN Web Design
1

#8 User is offline   Emily Dickinson 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 201
  • Joined: 17-September 10
  • Location:Albuquerque, NM

Posted 25 January 2011 - 12:59 PM

View Postmakro, on 09 January 2010 - 05:52 AM, said:

I think it could be a better solution put the code below into main.php layout file

I liked makro's solution best, thanks! I took it a bit further:
  • Color the submit button gray when clicked
  • Let the javascript event handler live in a file in the javascript directory, so that all of your javascript lives in one place, and does not live buried in php.
  • Register the javascript client script in your main controller. I.e., rather than
    cluttering the layout file, override the __construct() function for your default Controller class; so that your site as well as your modules can use it, and so that it works for all layouts.

Here's a working solution (except for Chrome!):

// 1. In your stylesheet, define the style "btn_gray":
btn_gray { 
    background-color: #efefef; 
}

// 2. Create the javascript file, "my-jquery.js", in the /javascript directory:
$(document).ready( function() {
   $(":submit").mouseup(function() {
      $(this).attr("disabled",true)
         .attr("class", "btn_gray")
         .parent().attr("class", "btn_gray")
         .parents("form").submit();
      });
})

// 3. Register the client script, in the constructor for your main Controller
public function __construct($id, CWebModule $module=null) {
   parent::__construct($id, $module);
   $baseUrl = Yii::app()->request->baseUrl;
   $clientScriptUrl = "{$baseUrl}/javascript/my-jquery.js";
   $clientScript = Yii::app()->clientScript;
   $clientScript->registerScriptFile($clientScriptUrl, CClientScript::POS_HEAD);
   // more construct code
}


This works on Firefox, MSIE. It fails on Chrome. If anyone knows why a registered client script might fail on Chrome, kindly update this post!

:mellow:
0

#9 User is offline   Antonio Ramirez 

  • Elite Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 1,448
  • Joined: 04-October 10

Posted 25 January 2011 - 08:30 PM

Hi Emily, I think the main problem is the mouseup option of your code. I would rather use another event, as it is going to be disabled after clicking, why not using 'click'. Have you tried your code in Safari? I am sure the interpretation of mouseup leads to troubles too.

Try this

$(document).ready( function() {
   $(":submit").click(function() {
      $(this).attr("disabled",true)
         .attr("class", "btn_gray")
         .parent().attr("class", "btn_gray")
         .parents("form").submit();
      });
})



if also fails, do not use 'parents()', just use the normal way of submitting or grab the id of the form to do so.
this.form.submit();
$('#formid').submit();


Nite... 3 am here
¿How long would it take for you to understand that you own nothing in this world?

www.ramirezcobos.com
www.2amigos.us
www.github.com/tonydspaniard
www.github.com/2amigos


Posted Image
0

#10 User is offline   Emily Dickinson 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 201
  • Joined: 17-September 10
  • Location:Albuquerque, NM

Posted 25 January 2011 - 10:43 PM

View PostAntonio Ramirez, on 25 January 2011 - 08:30 PM, said:

Hi Emily, I think the main problem is the mouseup option of your code.

Antonio, thanks SO much for replying at 3 a.m.!! (Or anytime.)

It turns out that the mouseup event is indeed the event to be handled; I just wasn't doing the form submission correctly, as you suggested. This works now:


$(document).ready( function() {
   $(":submit").mouseup(function() {
      $(this).attr("disabled",true)
         .attr("class", "btn_gray")
         .parent().attr("class", "btn_gray");
      this.form.submit();
   });
})



'Tis, now, a thing of beauty.

Thanks, again, for your help!
:-*
0

#11 User is offline   Emily Dickinson 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 201
  • Joined: 17-September 10
  • Location:Albuquerque, NM

Posted 26 January 2011 - 02:42 PM

Hey Antonio,
Actually, this solution works--exactly as you've written it--but it only works if my form consists of one or more inputs, plus a submit button.

IF, however, I create a CActiveForm widget, and only give it a single button, and no inputs, my controller ends up with an empty $_POST. I find this of course by inserting logging into my controller:

if ( empty($_POST))   {
   Yii::log("POST IS EMPTY!");
}


Any ideas?

Thanks so much...
Emily
0

#12 User is offline   Emily Dickinson 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 201
  • Joined: 17-September 10
  • Location:Albuquerque, NM

Posted 26 January 2011 - 03:20 PM

Okay, I used a slightly different approach, and now my $_POST array is never empty.

The clue you gave me, Antonio, that allowed me to figure this out, is that the submit button is being *disabled*. In the event handler below, we disable the button, color it gray, and then *re-enable* it.


$(document).ready( function() {
   $("form").submit(function(event) {
      var form = event.currentTarget;
      // Disable the button, turn the background gray, and set the text to "Working..."
      $("#" + form.id).find("input[type=submit]").attr("disabled",true)
         .attr("class", "btn_gray")
	 .attr("value", "Working...");

      // Submit
      form.submit();

      // Re-enable the button
      $("#" + form.id).find("input[type=submit]").attr("disabled",false);

      return true;
   });
})



Works in FF, MSIE, and Chrome.

Thanks again Antonio and others!

Emily
:)
0

#13 User is offline   Antonio Ramirez 

  • Elite Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 1,448
  • Joined: 04-October 10

Posted 26 January 2011 - 07:52 PM

Great you found the solution Emily,

Nevertheless, about your question on the empty Form, weird to drop an empty form but you could easily avoid form submission if form.elements.length are just the total number of buttons.

Anyway, I am wondering why you re-enable your submission button after you have submitted the form? I never done that after submission, only on the AJAX cases, wher e I need to handle buttons state. Any reasons for that?

Thanks in advance
¿How long would it take for you to understand that you own nothing in this world?

www.ramirezcobos.com
www.2amigos.us
www.github.com/tonydspaniard
www.github.com/2amigos


Posted Image
0

#14 User is offline   Emily Dickinson 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 201
  • Joined: 17-September 10
  • Location:Albuquerque, NM

Posted 26 January 2011 - 08:43 PM

Hi Antonio,

I found that disabling button is indeed problematic. So a simpler approach is to unbind the submit button from "click"; change the text to "Working..."; and change the color to gray.

So, here's the final solution, which works on FF, MSIE, and Chrome:

// 1. In your stylesheet, define the style "btn_gray":
btn_gray { 
    background-color: #efefef; 
}

// 2. Create the javascript file, "my-jquery.js", in the /javascript directory:
$(document).ready( function() {
   $(":submit").click(function() {
  // Only recolor the button if it's inside a "btn btn_green" div
   var containingDivClass = $(this).parent().attr("class");
   if (containingDivClass == 'btn btn_green')   {
      $(this).unbind("click").attr("value", "Working...").parent().attr("class", "btn btn_gray");
      this.form.submit();
      return false;  // must do this!!
   }
});

// 3. Register the client script, in the constructor for your main Controller
public function __construct($id, CWebModule $module=null) {
   parent::__construct($id, $module);
   $baseUrl = Yii::app()->request->baseUrl;
   $clientScriptUrl = "{$baseUrl}/javascript/my-jquery.js";
   $clientScript = Yii::app()->clientScript;
   $clientScript->registerScriptFile($clientScriptUrl, CClientScript::POS_HEAD);
   // more construct code
}

// 4. Use it, in a view. Explicitly name the button 'doit_button'
echo CHtml::submitButton('Doit', array('name'=>'doit_button'));

// 5. Check explicitly to see if form was submitted (this addresses
//    iGrog's question about the $_POST array, above)
if (isset($_POST['doit_button'])  )
    // do stuff
}


:mellow:
0

#15 User is offline   Emily Dickinson 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 201
  • Joined: 17-September 10
  • Location:Albuquerque, NM

Posted 27 January 2011 - 04:33 PM

I've noticed one gotcha with the javascript event handler as written:

If a page contains more than one form, even though only one form got submitted, all of the buttons get disabled, turned gray, etc. A usability issue. Ideas anyone?
0

#16 User is offline   Gustavo 

  • Master Member
  • Yii
  • Group: Moderators
  • Posts: 916
  • Joined: 27-July 10
  • Location:Curitiba - Brasil

Posted 27 January 2011 - 04:52 PM

use jquery closest to check which form was submitted
--
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application

Gustavo Salomé Silva
0

#17 User is offline   Emily Dickinson 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 201
  • Joined: 17-September 10
  • Location:Albuquerque, NM

Posted 27 January 2011 - 10:32 PM

Time to wrap this up. My question here isn't a Yii one, but a jQuery one. A working solution is on the jQuery forum, here:

http://forum.jquery....form-submission

Thanks Antonio and Gustavo!
:)
0

#18 User is offline   Gustavo 

  • Master Member
  • Yii
  • Group: Moderators
  • Posts: 916
  • Joined: 27-July 10
  • Location:Curitiba - Brasil

Posted 27 January 2011 - 11:05 PM

Im glad i could help
--
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application

Gustavo Salomé Silva
0

#19 User is offline   Tudor Ilisoi 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 22-January 11
  • Location:Radauti, Suceava, Romania

Posted 22 September 2011 - 02:30 PM

Hi, I came up with this solution for AJAX validated forms.
You just have to pass it the rigth selector for the submit button.
place this piece of code at the end of your _form.php partial views (and properly modify the button css selector).
<?php
$no_dbl_click=<<<EOD

   $("the_button").click(function(event) {      
   //extra_js;
   var target= $(event.currentTarget);
  // console.dir(target);
    if(!target.attr('disabled')){
    target.attr('rel',target.val());  
    }      
    target.attr("disabled",true)
         .attr("class", "btn_gray")
         .attr("value", "Un moment...");
      var the_expr="$('#" + target.attr('id') + "')";
      var the_statement=the_expr + '.attr("disabled",false).val(' + the_expr + '.attr("rel"))';      
      setTimeout(the_statement,2000);
     target.parents('form').submit(); 
     return true;
   });

EOD;
$js=str_replace('the_button','#form_submit',$no_dbl_click);
Yii::app()->clientScript->registerScript($this->id.'no_dbl_click',$js);
?>

Most important, this works with ajax and clientside validation, so the user may try again and again without reloading the page form. 2 secods is enough for the succesful post to redirect, and should be enough for validation messages to appear.
This code will disable the button for 2 seconds regardless if ajax/clientside form validation fails or succeeds.
It then attemps a submit on the parent form, which is the Yii generated form.
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • This topic is locked

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users