Search code examples
jqueryphalconvolt

Volt Template Engine inside of jQuery


I have a (maybe) pretty unique problem. You can see the picture below for better comprehension.

The pieces of equipment in the select area are fetched in the controller and then I loop through them with Volt an echo them in <option> tags, as in the code below:

<select class="form-control">
    <option value="0">No equipment</option>
    {% for item in equipment %}
    <option value="{{ item.id }}">{{ item.name }}</option>
    {% endfor %}
</select>

The user can press the plus-Button to add another Equipment. The whole <tr> is cloned and appended via jQuery. The problem is, when I want to loop through the equipment pieces. The volt code is not parsed, but rather echoed explicitly by jQuery, as visible in the picture below.

The cloning code is this (pretty hacky, I guess, I don't know of a better alternative to this, though):

$('#addEquipment').bind('click', function() {
    var $div = $('tr[id^="rowEquipment"]:last');
    var num = parseInt($div.prop('id').match(/\d+/g), 10) + 1;
    var $clone = $div.clone().prop('id', 'rowEquipment' + num);
    var $equipment = '<td>'+
        '<div class="row">'+
            '<div class="col-sm-1">'+
                '<p class="form-control-static">Equipment:</p>'+
            '</div>'+
            '<div class="col-sm-3">'+
                '<select class="form-control">'+
                    '<option value="0">No equipment</option>'+
                    '{% for item in equipment %}'+
                    '<option value="{{ item.id }}">{{ item.name }}</option>'+
                    '{% endfor %}'+
                '</select>'+
            '</div>'+
            '<div class="col-sm-1">'+
                '<p class="form-control-static">Notes:</p>'+
            '</div>'+
            '<div class="col-sm-3">'+
                '<input type="text" class="form-control" placeholder="Thickness mm / Weight kg">'+
            '</div>'+
            '<div class="col-sm-4">'+
                '<button id="' + num + '" class="btn btn-default removeEquipment"><span class="glyphicon glyphicon-remove"></span></button>'+
            '</div>'+
        '</div>'+
    '</td>';
    $div.after($clone.html($equipment));
    $('.removeEquiment').bind('click', function(evt) {
        var $id = $(evt.target).prop('id');
        var $removeEquipment = $('tr[id^="rowEquipment' + $id + '"]');
        $removeEquipment.remove();
    });
});

And here the picture:

enter image description here

Thank you for any advice!

EDIT:

The first solution from yergo (thank you) yields a SyntaxError: invalid property id, probably because {% for item in equipment %} is now treated as JavaScript and not as a string.

The second solution, when done like this:

var div = $('tr[id="cloneEquipment"]')[0];
var clone = div.cloneNode();
clone.parentNode.insertBefore(clone, div);

results in TypeError: clone.parentNode is null

Maybe important to mention (sorry, I forgot): the jQuery code is in a separate .js file

EDIT 2

I made an error: I was trying to append it to the parentNode of the cloned node, which obviously is bogus. Now, I'm this far:

Based on the second solution from yergo, I did some try&error in JSFiddle. Right now my solution looks like this:

var div = $('tr[id^="cloneEquipment"]');
var clone = div.clone();
clone.removeClass('hidden');
var cloneNode = clone[0].cloneNode();
div[0].parentNode.insertBefore(cloneNode, div[0]);

The cloning process seems to work, however it only clones the <tr> and not the contents of which.


Solution

  • After a lot of trial and error, I came to the following working code. All the clone.find() commands can be ignored. This was a pure jQuery problem all along and had nothing to do with Volt or Phalcon. Like this, the volt code is parsed correctly:

    $('#addEquipment').bind('click', function() {
        var div = $('tr[id^="rowEquipment"]:last');
        var num = parseInt(div.prop('id').match(/\d+/g), 10) + 1;
        var clone = div.clone();
        clone.prop('id', 'rowEquipment' + num);
        clone.find('.addEquipment').tooltip('disable');
        clone.find('.addEquipment').remove();
        clone.find('.helpEquipment').remove();
        clone.find('.removeEquipment').prop('id', num);
        clone.find('.removeEquipment').removeClass('hidden');
        $(div).after(clone);
        $('.removeEquipment').bind('click', function(evt) {
            var $id = $(evt.target).prop('id');
            var $removeEquipment = $('tr[id^="rowEquipment' + $id + '"]');
            $removeEquipment.remove();
        });
    });
    

    Here's a JSFiddle for those interested: clickerino