Chtml::beginform Autogenerated Hidden Fields

I still do not understand WHY the beginForm function generates hidden fields from action’s url.

Please can some explain?

I have found another topic wondering about it with but no answer.

Other Topic:

http://www.yiiframework.com/forum/index.php/topic/30520-many-hidden-fields-generated/page__p__147066__hl__form+hidden#entry147066

BeginForm reference:

http://www.yiiframework.com/doc/api/1.1/CHtml#beginForm-detail




if(!strcasecmp($method,'get') && ($pos=strpos($url,'?'))!==false)

    {

        foreach(explode('&',substr($url,$pos+1)) as $pair)

        {

            if(($pos=strpos($pair,'='))!==false)

                $hiddens[]=self::hiddenField(urldecode(substr($pair,0,$pos)),urldecode(substr($pair,$pos+1)),array('id'=>false));

            else

                $hiddens[]=self::hiddenField(urldecode($pair),'',array('id'=>false));

        }

    }



At first glance, what this code does is taking every parameter from the given action URL and create a hidden field for it if the method is POST.

Maybe that is not so strange in such case, considering the odd combination of GET parameters and a POST request ?

Hi,

You can find the revision here: Revision r1727

The reason is simple:

when you use a method=get form + url with query string (e.g. action="index.php?r=site/search&foo=bar") the querystring part will be cut off.

Example:




<form method="get" action="index.php?r=site/search&foo=bar">

  <input type="text" name="keywords" />

  <input type="submit" value="Search!" />

</form>



and if you submit the form the url will be something like this: hxxp://domain/index.php?keywords=something

if you want to send the r=site/search and foo=bar you need to add these by 1-1 form element (e.g. hidden field):




<form method="get" action="index.php">

  <input type="hidden" name="r" value="site/search" />

  <input type="hidden" name="foo" value="bar" />

  <input type="text" name="keywords" />

  <input type="submit" value="Search!" />

</form>



The questionable code does this.

You can find more information about this here: stackoverflow topic

ps.:

!strcasecmp($method,‘get’): strcasecmp(“GET”,‘get’) is 0 and the !0 is boolean true - this condition part is a little confusing but works

Ah, right! It is for the GET method, not the POST, that it will create the hidden fields.

(Yii is pretty clever, isn’t it! ;))

Thanks for the info. I ll try to find a way around it.

The thing is that I am submitting the form with ajax as such.

example code:




$(form).on('submit', function(){

    preventdefault etc.

    $.ajax({

        type: $(this).attr(method),

        url: $(this).attr(action),

        params: $(this).serialize(),

    })

})



And when the form’s method is “get”, it double sends the action’s query string parameters (like ‘r’ for example).

Once from the url and another from the serialized hidden field, which I do not wish to do so.

Anyway maybe my conceptual model is faulty and should not do it like that.

Thanks anyway.

Maybe try to disable these fields before serialize() - e.g.:




$(form).on('submit', function(){

    // ...

    var $queryStringElements = $("div:hidden:first-child :input",this);

    $queryStringElements.prop('disabled',true);

    var data = $(this).serialize();

    $queryStringElements.prop('disabled',false);

    // ...

    $.ajax({

        type: $(this).attr(method),

        url: $(this).attr(action),

        data: data,

    })

})



Could do, indeed, it helps that the autogenerated fields are at least wrapped in a div and follow the form tag immediatelly.

Thanks for the suggestion.