0

I am writing a dynamic form in the Play Framework, but I'm not very experienced with javascript. I'm trying to build off of this jQuery example that allows the dynamic addition of fields. Instead of adding only a text field, I want to add a text field and a select box each time. The tricky part is that even if there is a selected item, I want the dynamically added select box to be reset.

Here is my attempt to do this, using this answer

 $('.multi-field-wrapper').each(function() {
   var $wrapper=$('.multi-fields', this);
   $(".add-field", $(this)).click(function(e) {
     var obj=$('.multi-field:first-child', $wrapper).clone(true).appendTo($wrapper).find('input').val('').focus();
     // This following line is incorrect...
     obj.find('.blank').prop('selected', true).end().trigger('chosen:updated');
   }
   );
   $('.multi-field .remove-field',
   $wrapper).click(function() {
     if ($('.multi-field', $wrapper).length > 1) $(this).parent('.multi-field').remove();
   }
   );
 }
 );
<form role="form" action="/wohoo" method="POST">
  <label>Stuff</label>
  <div class="multi-field-wrapper">
    <div class="multi-fields">
      <div class="multi-field">
        <div>
            <input type="text" name="stuff[]"/>
        </div>
        <div>
            <select>
              <option class="blank" value="">Select a car</option>
              <option value="saab">Saab</option>
              <option value="mercedes" selected>Mercedes</option>
              <option value="audi">Audi</option>
            </select>
        </div>
        <button type="button" class="remove-field">Remove</button>
      </div>
    </div>
    <button type="button" class="add-field">Add field</button>
  </div>
</form>

Since it uses the clone() function, if "Mercedes" is selected, then dynamically added select dropdowns will also have "Mercedes" selected. How can I make the new selects display the blank choice?

Thanks!

EDIT - updated my code to reflect the fact that my input and select tags are encapsulated by divs

Community
  • 1
  • 1
KJ50
  • 765
  • 1
  • 10
  • 27
  • why clone when you can create a new element to insert? – Traveling_Monk Feb 26 '15 at 19:48
  • Good question. I suppose it's because the original jsfiddle example I found used `clone()`. This question is actually from the context of a web application using the Play framework, and in there I am dynamically adding to a view template that contains a select element like this. – KJ50 Feb 26 '15 at 19:54

2 Answers2

3

The "obj" variable becomes the input node selected in the end of this expression:

var obj = $('.multi-field:first-child', $wrapper).clone(true).appendTo($wrapper).find('input').val('').focus();

But you should do the trick with select node, in your case it is "obj"`s sibling.

 obj.siblings('select').find('.blank').prop('selected', true).end().trigger('chosen:updated');});

http://jsfiddle.net/xogeufa2/1/

Also, if "input" and "select" nodes are enveloped in div tags, they loose their sibling relations. So in this case, you should find another way, to get the "select". For example, through parents:

obj.closest('.multi-field').find('select').find('.blank').prop('selected', true).end().trigger('chosen:updated');
    });

http://jsfiddle.net/2ymd7ug7/2/

Alexandr Lazarev
  • 12,554
  • 4
  • 38
  • 47
  • I over-simplified my example a little bit. In my actual application, I have a `div` surrounding the `input` and `select` elements. Thus, when I try your solution in that case it doesn't work http://jsfiddle.net/2ymd7ug7/1/ How do I change the `siblings()` line to work if they are inside of divs? – KJ50 Feb 26 '15 at 20:16
  • Well, in your case "select" and "input" nodes are not siblings anymore, instead, their parents became. In this case it would be easier to climb up to "multi-field", and then look through all it`s children for a "select" node. After "select" was found, do the trick. Here we go: http://jsfiddle.net/2ymd7ug7/2/ ps: Updated my answer. – Alexandr Lazarev Feb 26 '15 at 20:24
  • Thank you! Today I learned about `siblings()` and `closest()` =) – KJ50 Feb 26 '15 at 20:33
2

You just needs to remove the attribute selected from the option tag.

For that you can use removeAttr method

Here is the complete code that does what you described.

$('.multi-field-wrapper').each(function() {
    var $wrapper = $('.multi-fields', this);
    $(".add-field", $(this)).click(function(e) {
        var obj = $('.multi-field:first-child', $wrapper).clone(true).appendTo($wrapper).find('input').val('').end().find('option').removeAttr('selected').focus();
    });

    $('.multi-field .remove-field', $wrapper).click(function() {
        if ($('.multi-field', $wrapper).length > 1)
            $(this).parent('.multi-field').remove();
    });
});

Just added .end().find('option').removeAttr('selected') to your code :)

I hope I helped..

Find the code here : https://jsfiddle.net/yrchyndk/

VIVEK SEDANI
  • 407
  • 4
  • 15
  • 1
    I like your solution because it is more concise. One thing that I would change is keep the focus on the text field, so I used this `$('.multi-field:first-child', $wrapper).clone(true).appendTo($wrapper). find('input').val('').focus().end(). find('option').removeAttr('selected');` https://jsfiddle.net/frkjyv87/2/ – KJ50 Feb 26 '15 at 21:13