使用输入类型编号和onchange事件的动态表单

问题描述:

I have the form on the picture, and I want the "numero de cuartos" field to append the same amount of inputs of "numero de personas adultas" and "numero de niños", additionally, the "numero de niños" input needs to append the same amount of "edad de niños" inputs.

Dynamic Form

I have it like this:

<!--INPUT TYPE NUMBER OF Numero de cuartos-->
<div class="col-md-6 col-sm-6">
  <div class="form-group">
  <label>Numero de cuartos</label>
  <input required type="number" id="cuartos" name="cuartos" onchange="insertarCampos();" class="form-control" min="0"/>
 </div>
</div>

<!--Place to append-->
<div id="contenidoPersonas"> 
</div>

<!-- This form is appended depending on the number of "numero de cuartos" input -->
<div id="rooms" style="display:none;">
                                <div class="row">
                                    <div class="col-md-4 col-sm-4">
                                        <div class="form-group">
                                            <label>Numero de personas adultas</label>
                                            <input required type="number" id="adulto" name="adulto[]" class="form-control" min="1" max="6"/>
                                        </div>
                                    </div>
                                    <div class="col-md-4 col-sm-4">
                                        <div class="form-group">
                                            <label>Numero de niños</label>
                                            <input required type="number" id="nino" name="nino[]" class="form-control" min="0" max="6" onchange="insertarEdadesNinos();"/>
                                        </div>
                                    </div>
                                    <div class="col-md-4 col-sm-4">
                                      <!-- Inside edadNinos div goes the div with id "ninos"--> 
                                        <div id="edadNinos">
                                        </div>
                                    </div>
                                </div>
                            </div>
                                
 <!-- This form is appended on the "edadNinos" div depending on the number of "numero de niños" input -->
                                <div id="ninos" style="display:none;">
                                    <div class="form-group">
                                        <label>Edad de niños</label>
                                    <input required type="number" id="edadNino" name="edadNino[]" class="form-control" min="0" max="12"/>
                                    </div>
                                </div>

THE JAVASCRIPT:

function insertarCampos(){
            var personasSingle = $('#cuartos').val();

            for(i = 0;i < personasSingle;i++){
                $('#contenidoPersonas').append($('#rooms').html());
                $('#contenidoPersonas').append("<hr>");
            }
        }

        function insertarEdadesNinos(){
            var numNinos = $('#nino').val();
            $('#edadNinos').empty();
            for(i = 0;i < numNinos;i++){
                $('#edadNinos').append($('#ninos').html());
            }
        }

This appends the things correctly, like in the picture, but there are some problems:

  • If I change my mind and instead of "2", I put 1, the inputs are erased and appended again because of the empty function and I don't know how to correct that.

  • The other thing is that the "numero de niños" input only works on the first one, the second "numero de niños" input doesn't do anything because it has the same id as the first one, I don't know how to correct that either.

I also need to send those inputs separated to a PHP script, the separation is marked visually on the form of the picture with the tag

<hr>

Thanks!

</div>

What you are trying to do is emulate how templates work, but is not a very good idea just use the HTML of DOM elements that are already in the document (maybe you can use replace to change the HTML but that would be a very nasty solution), I recommend you to take a look at how jQuery templates work http://jsfiddle.net/zarjay/ZAkM7/ in the meanwhile this code will do what you are trying to achieve:

(You also need to add the reference the jQuery templates plug in) http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js)

<!--INPUT TYPE NUMBER OF Numero de cuartos-->
<div class="col-md-6 col-sm-6">
    <div class="form-group">
        <label>
            Numero de cuartos
        </label>
        <input required type="number" id="cuartos" name="cuartos" onchange="insertarCampos();" class="form-control" min="0" />
    </div>
</div>
<br />
<!--Place to append-->
<div id="contenidoPersonas">
</div>
<!-- This form is appended depending on the number of "numero de cuartos" input -->
<script id="roomsTemplate" type="x/jquery-tmpl">
    <div class="room" room-number="${roomNumber}">
        <div class="row">
            <div class="col-md-4 col-sm-4">
                <div class="form-group">
                    <label>
                        Numero de personas adultas
                    </label>
                    <input required type="number" id="adulto" name="adulto[]" class="form-control" min="1" max="6" />
                </div>
            </div>
            <div class="col-md-4 col-sm-4">
                <div class="form-group">
                    <label>
                        Numero de ni�os
                    </label>
                    <input required type="number" name="nino[]" class="nino form-control" min="0" max="6" onchange="insertarEdadesNinos(${roomNumber});" />
                </div>
            </div>
            <div class="col-md-4 col-sm-4">
                <!-- Inside edadNinos div goes the div with id "ninos"-->
                <div class="edadNinos">
                </div>
            </div>
        </div>
    </div>
    <hr room-number="${roomNumber}" />
</script>
<!-- This form is appended on the "edadNinos" div depending on the number of "numero de ni�os" input -->
<script id="ninosTemplate" type="x/jquery-tmpl">
    <div class="ninos" nino-number="${ninoNumber}">
        <div class="form-group">
            <label>
                Edad de ni�os
            </label>
            <input required type="number" class="edadNino" name="edadNino[]" class="form-control" min="0" max="12" />
        </div>
    </div>
</script>

The javascript:

function insertarCampos() {
        var personasSingle = $('#cuartos').val();
        var currentRooms = $('#contenidoPersonas .room').length;

        if(personasSingle > currentRooms) {
            for (var i = currentRooms; i < personasSingle; i++) {
                $('#roomsTemplate').tmpl({ roomNumber: i }).appendTo('#contenidoPersonas');
            }
        }
        else {
            for (var i = currentRooms; i > personasSingle; i--) {
                $('[room-number="'+(i - 1)+'"]').remove();
            }
        }
    }

    function insertarEdadesNinos(roomNumber) {
        var numNinos = $('.room[room-number="'+roomNumber+'"] .nino').val();
        var currentNinos = $('.room[room-number="'+roomNumber+'"] .edadNino').length;

        if(numNinos > currentNinos) {
            for (i = currentNinos; i < numNinos; i++) {
                $('#ninosTemplate').tmpl({ ninoNumber: i }).appendTo('.room[room-number="'+roomNumber+'"] .edadNinos');
            }
        }
        else {
            for (var i = currentNinos; i > numNinos; i--) {
                $('[room-number="'+ roomNumber +'"] [nino-number="'+(i - 1)+'"]').remove();
            }
        }
    }

Also this aproach is a bit outdated, you can also look some MVC framework like http://knockoutjs.com which is not very complicated.

Ok, there are some problems in this script.

First: an ID is unique!

The id global attribute defines a unique identifier (ID) which must be unique in the whole document.

You could use classes for elements you want to copy / clone. To select these elements, JQuery has these wonderful Class Selectors.

Or you could change the Id of these elements:

$('#rooms').clone().attr('id', 'rooms' + myIndex)

If you copy append elements into the DOM, you have to save references to these elements, so that you are able to remove them later. This can be done, by putting them into an array:

var rooms = new Array();
....
for(....) {
    var ref = $('#rooms').clone().attr('id', 'rooms' + myIndex);
    rooms.push(ref);
}

Or you work with the generated IDs and the ID-Selector ... your choice.

To select the "Numero de niños" input field in one of the cloned trees, you can use a JQuery Child Selector. On the reference you could register a change event handler. There you can register a function, which is called every time the input field is changed.