[solved] Change form action using jQuery

Has anyone tried to modify the action attribute of a form using jQuery?

I’m trying to submit a form containing a CJuiAutocomplete widget. As a default/ fallback, I want to perform a search action. But if the user clicks on one of the items suggested by the autocomplete widget, I’d like to submit to the view action instead.

The weird thing is: I can see that the attribute changes, however if I click the submit button or try to submit the for using javascript, the browser will still submit to the old URL (search action).

Any ideas on this?

I’m using the following code:




jQuery('#term').autocomplete({

    'showAnim': 'fold',

    'source': '/yiiFeatureRequestDemo/index.php?r=featureRequests/features/search&encode=json',

    'focus': function( event, ui ) {

        var hoveredText = ui.item.message.title;

        var decoded = $("<div/>").html( hoveredText ).text();

        $(this).val( decoded );


        return false;

    },

    'select':function( event, ui ) {

        var hoveredText = ui.item.message.title;

        var decoded = $("<div/>").html( hoveredText ).text();

        $(this).val( decoded );


        $(this).siblings( "input[type=submit]" ).val( "Go" );

        $(this).siblings( "input[type=hidden]" ).attr( "name", "id" );

        $(this).siblings( "input[type=hidden]" ).val( ui.item.id );


        // This seems to work

        $(this).closest( "form" ).attr( "action", "/yiiFeatureRequestDemo/index.php?r=featureRequests/features/show" );

        

        // TODO: for some reason, this will cause a search, although the the form action has been modified..

        // $(this).closest( "form" ).submit();


        return false;

    }

});



Do you need a form?

Why not just submit it via post from a ‘normal’ Ajax action?

Well, I could make it an ajax request, replacing the current content of the page with a partially rendered view. It’s only that the app currently isn’t using much ajax (the search and yii’s controls when paging). So it wouldn’t really fit in. What I also worry about is the problem with scripts that run on document.ready(). If the view used such scripts, I ran into new problems using the ajax-loading aproach. That’s why I’d like to stick with normal requests at the moment.

Maybe I don’t see anything really obvious. I really wonder about that behavior. Think I’ll try to build a new form in jQuery and submit that… At least until I find a better solution (or decide to go ajax :) ).

This keeps bugging me. I changed the code to append a new form to my site:




$this->CJuiAutoComplete['options']['select'] = 'js:function( event, ui ) {

    var viewUrl = "'.CHtml::normalizeUrl($this->viewUrl).'";

    var viewFormHtml = \'<form action="\' + viewUrl + \'" method="get">\

        <input type="hidden" value="3" name="id">\

    </form>\';


    $(viewFormHtml)

        .appendTo("body")

        //.submit()  // line commented to verify what gets appended

    ;


    return false;

}';



So with this, I can see the following snippet of html being attached to my page’s body as last child:




<form action="/yiiFeatureRequestDemo/index.php?r=featureRequests/features/show" method="get">

    <input type="hidden" value="3" name="id">

</form>



But if I enable the commented “submit()” line, the form gets submitted directly to my index.php, with the id param in query. So almost everything works as expected: DOM manipulation, submit method is recognized, the inputs get evaluated, only that damn action attribute refuses to do what I want. :angry:

Does anyone know something about this issue? Is the action attribute somehow protected?

// EDIT:

Is it possible that the query string gets removed from the action, because I’m using “get”-method? So the browser builds the query from the inputs, and instead of attaching them to the “action”-url, it replaces the “action”-url’s query part with the newly generated one?! Anyone knows where this might be specified?

I can make it work by introducing a new hidden input containing the "r"-param…

ok in reply to your last post, yes the query string will get removed and yes you’ll probably have to pass it through as a hidden input.

Generally though you’re kind of going about this the wrong way. What i’d do is have a hidden attribute with name=action and value=youraction and just modify that. Have the action submit to a processing function e.g. /myapp/index and work the logic out in the controller so if action = blah load function blah() etc. Then do a redirect form within your php code once you’ve processed it to your desired destination.

Thanks for sharing your thoughts.

I will consider this. However, I don’t like the idea of introducing new server side code dealing with logic that is only needed for a client side improvement. But a hidden input with name=r and value=route/to/action would do it without the need of new server side code.

But then I wonder how to deal with a SEO feature that might get enabled. I think there’s no need to provide SEO-urls for the search. But at least for the view-action, there wouldn’t be get-params any more. I have to think about this all a bit more.

Guess the easiest way would be changing that action-attribute. ^^

So if anyone knows something about why it can’t be changed, please let me know. Would save me from all these workarounds. I found several resources dealing with manipulation of of form-action-attribute. The answers are all very straight forward, like “$(form).attr(“action”, “newUrl”);”. But no complaints about it wouldn’t work, which makes me wonder if it might be some side effect with my code…

[color="#006400"]/* moved to proper forum */[/color]

Omg, i can’t believe I didn’t notice this!

CHtml::beginForm correctly cares for generating hidden inputs for all query parameters when using get-method. Since my javaScript code only ever modified the form action’s query part of the url, which will be recreated by the browser from existing input fields, those modifications basically got reverted on submit…