1
\$\begingroup\$

For a form I got the markup below, it belongs to an input category and as there can be more than one insertion at it I includded an Añadir button (Add).

I give id="posgrado1" to first div and using Java Script I increment the id's to posgrado2, posgrado3, ... posgrado#n

<div class="form-group" id="posgrado1">

    <label for="checkPosgrado" class="col-xs-2 control-label">Estudios de Posgrado</label>

    <div class="col-xs-2">
        <select class="form-control inputPosgradoTipo">
            <option>Especialidad</option>
            <option>Maestría</option>
            <option>Doctorado</option>
        </select>               
    </div>

    <div class="col-xs-4">
        <input type="text" class="form-control inputPosgradoTitulo" placeholder="Título">                       
    </div>

    <div class="col-xs-3">
        <input type="text" class="form-control inputPosgradoCedula" placeholder="Cédula">
    </div>

    <div class="col-xs-1">
        <input type="button" class="form-control btnAñadirPosgrado" value="Añadir">
    </div>
</div>

Each html within a class got a class identifying the type of input.

So far this is how I add more input instances:

numPosgrados = 1

function agregarPosgrado () {


    var markupPosgrado="";
    markupPosgrado += "                    <div class=\"form-group\" id=\"posgrado";
    markupPosgrado += (++numPosgrados)+"\">";
    markupPosgrado += "                        ";
    markupPosgrado += "                        <label for=\"checkPosgrado\" class=\"col-xs-2 control-label\"><\/label>";
    markupPosgrado += "";
    markupPosgrado += "                        <div class=\"col-xs-2\">";
    markupPosgrado += "                            <select class=\"form-control inputPosgradoTipo\">";
    markupPosgrado += "                                <option>Especialidad<\/option>";
    markupPosgrado += "                                <option>Maestría<\/option>";
    markupPosgrado += "                                <option>Doctorado<\/option>";
    markupPosgrado += "                            <\/select>                ";
    markupPosgrado += "                        <\/div>";
    markupPosgrado += "";
    markupPosgrado += "                        <div class=\"col-xs-4\">";
    markupPosgrado += "                            <input type=\"text\" class=\"form-control inputPosgradoTitulo\" placeholder=\"Título\">                        ";
    markupPosgrado += "                        <\/div>";
    markupPosgrado += "";
    markupPosgrado += "                        <div class=\"col-xs-3\">";
    markupPosgrado += "                            <input type=\"text\" class=\"form-control inputPosgradoCedula\" placeholder=\"Cédula\">";
    markupPosgrado += "                        <\/div>";
    markupPosgrado += "";
    markupPosgrado += "                    <\/div>";

    $("#posgrado"+(numPosgrados-1)).after(markupPosgrado)
}

For getting the information I'd like to return a JSON, like:

function obtenerPosgrados () {

    return {EachInstance: {eachInputTypesForEach}}
}

This is an example fiddle.

What's a better implementation of this? Can I take more advance of jQuery or any other JavaScript library?

\$\endgroup\$
3
\$\begingroup\$

A better way is to use templates. Handlebars should be a good start for this.

Here's a quick demo:

HTML:

<!-- our target -->
<div id="container">

</div>

<!-- the template (Note the type. This prevents if from running as a script. -->
<script type="text/template" id="template">
  {{#each people}}
    <b>{{id}}</b> : <i>{{name}}</i>
  {{/each}}
</script>

JS:

// The data.
var data = {
  people : [
    {
      id : 1,
      name : 'Alice'
    },{
      id : 2,
      name : 'Bob'
    }
  ]
};

// We get the template HTML
var template = $('#template').html();

// Compile it as a handlebars template renderer
var renderer = Handlebars.compile(template);

// and just feed in the data into the renderer to return the HTML with the data
var html = renderer(data);

// Then all we need to do is pop-in the HTML with the data to our page
$('#container').html(html);

The rest is up to you. You can use the demo as your guide. You can use the id of the data as your n. Handlebars also provides you the index if you loop through an array in the template, which you could also use as your n.

\$\endgroup\$
  • \$\begingroup\$ Would you recommend it more against AngularJS? \$\endgroup\$ – diegoaguilar May 12 '14 at 5:39
  • \$\begingroup\$ @diegoaguilar Handlebars is merely a templating library. Angular is a framework. They're different things. Angular has a built-in template system. \$\endgroup\$ – Joseph May 12 '14 at 5:42
1
\$\begingroup\$

Personally I think you are over complicating things. It is fine that you use jQuery, because it makes javascript a whole lot easier, but that should be all you need. Js libraries are fine, but you should not use them just because you can.

You could indeed go for a templating language as suggested, but that is not rely required imo. All you are doing is duplicating a row in your form, so why don't you use that row in the form as your template. All you have to do is clone it, append it, and reset the values.

This is what I came up with (with a ridiculous amount of comments):

// on click of all current and future buttons with class ...
$("body").on('click', '.btnAñadirPosgrado', function () {
    // select the last form row
    $('.form-row:last')
    // clone it
    .clone()
    // append it to the list of form-rows
    .appendTo('.form-rows')    
    // set all the values to empty, except the button
    .find('input, select').not('[type="button"]').val('');        
});

Note that I altered the html slightly just to make my example a bit easier. A working demo is in the updated fiddle: http://jsfiddle.net/TufL4/2/

A few remarks on this approach:

  • I removed the ID. Not sure why you would need it, and it just makes things more complicated then needed. You could off course add it back, but personally I think a class would be better suited here. You are using multiple instances after all...
  • The big advantage of this method is, that when you ever want to change something to your form, you can do so in your html, without having to change a single line of javascript. You know what they say, a good programmer is a lazy programmer, and I hate to write the same line of code more then once!
  • Do note that when you start adding name attributes to your form (I suspect you are going to submit it some day) you should add square braces (myName[]) to make them act as arrays. This way you can just keep the js as is. Or you could re-invent that counter system and add custom names if you prefer.

And one final thing, which is completely irrelevant, but I find it very important. Please write all your code in English. Functions, classes, variables, everything. It is the language of programmers, and it makes it a lot easier to ask for help online, or collaborate with others. I am not a native English speaker myself, but I do not write a single line of code in my own language. (I recently had to work on some code that was written by a French developer, in french, quel horeur!). Your english seems more then good enough, and it will only improve from writing in english!

\$\endgroup\$
  • \$\begingroup\$ Thanks! I agree with all your suggests. I would only like to know what would it be your alternative to catch all inputs? \$\endgroup\$ – diegoaguilar May 14 '14 at 3:34
  • \$\begingroup\$ You could put a form around it all, add name attributes to the fields and then use serializeArray on it. Or you could write your own parser, something like this perhaps: jsfiddle.net/TufL4/3 \$\endgroup\$ – Pevara May 15 '14 at 22:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.