Oleg
Oleg

Reputation: 24988

Change input value or add a new input if it doesn't exist

Background: I need to append certain data to post; similar to what jQuery's ajaxSetup does that for asynchronous requests except I need it for native form submits.

I need to be able to add a couple of form fields to a form before it is submitted, but I want to make sure I don't add duplicate fields in case they're already there (i.e. original submit failed because of validation or something).

At first I thought something like this would be nice and coherent:

$("form").live("submit", function () 
{
    var $this = $(this);

    ($this.find('#stuff') ||
    $this.append('<input type="hidden" id="stuff" name="stuff" />'))
        .val('some value');

    // carry on with the native submit
    // this is actually correct, as opposed to $this.submit()  
    // which would create a loop

    this.submit();
});

Meaning look for #stuff, if it's not found create it, then set its value to "some value". However because the result of the .find() is actually a jQuery wrapper, it would be implicitly converted to a true meaning that even if there are no matching elements found, the .append() code would never be executed.

Is there a nice way to tackle this whole "look for an element and create it if it doesn't already exist" scenario?

Upvotes: 0

Views: 2179

Answers (2)

Oleg
Oleg

Reputation: 24988

To keep checking logic readable one would expand the conditional:

if ($this.find('#stuff').length) {
  $this.find('#stuff').val('some val');
} else {
  $this.append('<input type="hidden" id="stuff'" name="stuff" value="some val" />');
}

Alternatively one could just remove and re-add the element... I know, "dom operations are expensive" but if there are several fields to be operated on it's just so much prettier this way:

$this.find('#stuff', '#stuff2', ...).remove()
  .append('<input type="hidden" id="stuff" name="stuff" value="some val" />...');

Upvotes: 0

Josh
Josh

Reputation: 3284

change $this.find('#stuff') to $this.find('#stuff').length

edit

if you want to be able to all of it in one statement you can do

(
 ($this.find('#stuff').length && $this.find('#stuff')) || 
  $('<input type="hidden" id="stuff" name="stuff" />').appendTo($this)
).val('some val');

Upvotes: 2

Related Questions