Ian Vermeulen
Ian Vermeulen

Reputation: 3

Dynamically add input fields when needed

I'm trying to add extra input fields to my HTML form as they are needed. Here's my code:

My code

JS

$(document).ready(function(e) {
    var i = $('.form-inputs input').size() + 1;

    $('.section-topic-field').last().bind('keyup', function(e) {
        if($(this).val() != "") {
            var html_new_field = '<input name="txtTopicName' + i + '" class="section-topic-field" type="text" onfocus="this.value=\'\'" placeholder="topic name #' + i + '" /><br />';

            $('.form-inputs').append($(html_new_field).fadeIn('slow'));

            i++;
        }
    });
});

HTML

        <input name="txtSection" type="text" onfocus="this.value=''" placeholder="sections"/><br/>
    <div class="form-inputs">
        <input name="txtTopicName1" class="section-topic-field" type="text" onfocus="this.value=''" placeholder="topic name #1"/><br />
     </div>
    <!--<button class="btn btn-mini btn-primary" type="submit">Create</button>-->
</form>

The problem

However, the function ALWAYS triggers on the first input field, so typing ,for example, 4 letters in the first input field, will generate 4 input fields. And when you then type something in the actual last input field (the 4th in this case) nothing happens. So for some reason $('.section-topic-field').last() always selects the first input field.

I also tried the :last selector and the :last-child, but result is just the same

Any help?

Thanks!

Upvotes: 0

Views: 1718

Answers (3)

Spokey
Spokey

Reputation: 10994

Since you are adding the input dynamically I suggest you use .on().

var i = $('.form-inputs input').size() + 1;

$('.form-inputs').on('keyup', '.section-topic-field:last', function (e) {
    if ($(this).val() != "") {
        var html_new_field = '<input name="txtTopicName' + i + '" class="section-topic-field" type="text" onfocus="this.value=\'\'" placeholder="topic name #' + i + '" /><br />';
        $('.form-inputs').append($(html_new_field).fadeIn('slow'));
        i++;
    }
});

Fiddle here

Unfortunately I'm not good at explaining but here you can find a short summary for the on() method. Stackoverflow link;

As said in the answer above

$("static selector").on('click', "dynamic selector", fn);

Given the parameters above, the on() method will search for the dynamic selector in the static selector when it is focused, clicked etc..

Using it like

$("static selector").on('click', fn);

Will work like a normal .click()

Upvotes: 1

Ed_
Ed_

Reputation: 19098

You are binding an event listener to the last field that exists on document ready - which is actually the first (and only) field. This event listener stays on that exact field for the duration of its existence, or until you unbind the listener.

Remember, you are not running the whole of your quoted code every time a key is lifted, only the function you pass to the listener.

You need the following logical flow:

  1. Create the first input element
  2. Bind an event listener to that element once the user has stopped tying* which will create a new element if the current one is not empty
  3. When that event fires:
    • create a new input element
    • unbind the original listener you created in 2
    • bind a new listener to the new input element (with the same functionality)

*keyup is not a good event to bind to in this case, because this will trigger as soon as the user types the first letter. You should probably consider instead using blur, or waiting some number of seconds before triggering the event (see setTimeout). Alternatively you could use a button for the user to explicitly request a new input field?

Let me know if you need some examples.

Upvotes: 0

Davor
Davor

Reputation: 1237

It's creating a new field each time you have a keyup event - it's not linked to :last. I'm not sure how to fix it but if($(this).val() != "") doesn't work there so each new character entered will trigger one more field. How about using $('.section-topic-field').change(function() { ...}); instead?

Upvotes: 0

Related Questions