We work with jQuery Templates. Part Three, jQuery Templates Plus

Published on February 14, 2011

We work with jQuery Templates. Part Three, jQuery Templates Plus

    Two weeks ago, I talked about the main features of the jQuery Templates plugin and promised not to stop there. Promises must be kept, so today I will talk about additional functions that are not included in the main code of the plugin.

    Additional plugin features include:
    1. A set of commands that greatly simplify changing rendered templates when changing data associated with them;
    2. The rendered event that is raised after the rendered template is added to the document structure.

    The code for additional functions has been moved to the jquery.tmplPlus.js file , so to use them you must add a link to this file:

    <script src="Scripts/jquery-1.5.js" type="text/javascript"></script>
    <script src="Scripts/jquery.tmpl.js" type="text/javascript"></script>
    <script src="Scripts/jquery.tmplPlus.js" type="text/javascript"></script>



    Commands for changing rendered templates


    Challenge teams


    To call all the commands, use the jQuery.tmplCmd () method .

    This method has three forms of invocation:
    1. jQuery.tmplCmd (command, tmplItem)
    2. jQuery.tmplCmd (command, tmplItems)
    3. jQuery.tmplCmd (command, data, tmplItems)

    The command parameter is used to specify the command name ( update , remove , replace, or find ).

    The tmlItem parameter is used to pass a reference to the template instance with which the command will work. Accordingly, the tmplItems parameter is used to pass an array of links to template instances.

    The data parameter can be a reference to a data element or an array of such links and is used to filter the tmplItems array . If this parameter is specified, not all instances of templates will participate in the operation, but only those associated with those specified in the data parameter data items:



    Which of these three forms of invocation are applicable for each command, I will indicate in the description of these commands.

    Replace command


    The replace command is perhaps the most interesting of all, it changes the order of rendered templates in the document structure in accordance with the order specified by its arguments, and without re-rendering the templates.

    This command allows three forms of invocation, but only one of them has practical application:
    1. jQuery.tmplCmd ('replace', data, tmplItems)

    After the replace call, the rendered templates will be rearranged in the order in which data elements are referenced in the data array. The perfect solution for sorting!

    Let’s now see how it works. The data that I will work in this and other examples in this section are in dataItems array (full sample code - file Samples.htm ):

    var dataItems = [
        { firstName: 'Брюс', lastName: 'Уиллис' },
        { firstName: 'Билли Боб', lastName: 'Торнтон' },
        ...
    ];

    To display this data, I use the following template:

    <script id="item_tmpl" type="text/x-jquery-tmpl">
        <tr class="item">
            <td>${firstName}</td>
            <td>${lastName}</td>
            <td>
                <img src="Images/item-edit.png" class="item-edit" title="Edit" />
                <img src="Images/item-delete.png" class="item-delete" title="Delete" >
            </td>
        </tr>
    </script>

    After rendering, I save links to all instances of the template in the tmplItems array :

    $('#item_tmpl').tmpl(dataItems, options).appendTo('#items_bag');
    tmplItems = $('#items_bag .item').map(function () {
        return $.tmplItem(this);
    }).get();

    I attach event handlers to pictures marked with the sort-asc and sort-desc classes in the table header. The optional x-field-name attribute contains the name of the field to sort by:

    <table id="items_bag">
        <tr>
            <th>First Name
                <img src="Images/sort-asc.png" class="sort-asc" x-field-name="firstName" alt="" />
                <img src="Images/sort-desc.png" class="sort-desc" x-field-name="firstName" alt="" />
            </th>
            <th>Last Name
                <img src="Images/sort-asc.png" class="sort-asc" x-field-name="lastName" alt="" />
                <img src="Images/sort-desc.png" class="sort-desc" x-field-name="lastName" alt="" />
            </th>
            <th></th>
        </tr>
    </table>

    The code for ascending sorting is shown below:

    $('#items_bag').delegate('.sort-asc', 'click', function () {
        var fieldName = $(this).attr('x-field-name');
        dataItems.sort(function (a, b) {
            return compareStrings(a[fieldName], b[fieldName]);
        });
        tmplItems = $.tmplCmd('replace', dataItems, tmplItems);
    });

    Here I first get the name of the field to sort by:

    var fieldName = $(this).attr('x-field-name');

    Then I sort the array with the data elements:

    dataItems.sort(function (a, b) {
        return compareStrings(a[fieldName], b[fieldName]);
    });

    And finally, I call the replace command to display the changed data in the document:

    tmplItems = $.tmplCmd('replace', dataItems, tmplItems);

    The replace command returns an array of links to template instances located in the same order as the rendered templates in the document, so I save the result of the replace run in tmplItems .

    The code for sorting in descending order looks similar:

    $('#items_bag').delegate('.sort-desc', 'click', function () {
        var fieldName = $(this).attr('x-field-name');
        dataItems.sort(function (a, b) {
            return compareStrings(a[fieldName], b[fieldName]);
        }).reverse();
        tmplItems = $.tmplCmd('replace', dataItems, tmplItems);
    });

    How it works is shown in the video below:



    Update command


    The update command initiates a re-rendering of the templates. In fact, this is the equivalent of the update () method of the template instance with additional options. Its most logical use is to update the document after changing the data.

    This command allows three forms of invocation, and, unlike the replace command , all of these forms have practical applications:
    1. jQuery.tmplCmd ('update', tmplItem)
    2. jQuery.tmplCmd ('update', tmplItems)
    3. jQuery.tmplCmd ('update', data, tmplItems)

    Let's see how it works with the example of the table editor (the full example code is in the Samples.htm file ). The code for editing the item is shown below:

    $('#items_bag').delegate('.item-edit', 'click', function () {
        var tmplItem = $.tmplItem(this);
        var dataItem = tmplItem.data;
        editDialog.show(dataItem, function () {
            $.tmplCmd('update', tmplItem);
        });
    });

    Here I first get a link to the template instance and a link to the data item:

    var tmplItem = $.tmplItem(this);
    var dataItem = tmplItem.data;

    Then I call the dialog box to which I pass the link to the data item and a callback function that will be called if the user clicked OK, and the data has been changed:

    editDialog.show(dataItem, function () {
        $.tmplCmd('update', tmplItem);
    });

    And in the callback function, I call the update command , giving it a link to the template instance, which causes it to be rendered again:

    $.tmplCmd('update', tmplItem);

    How it works is shown in the video below:



    Remove command


    The remove command, as you might guess, removes rendered templates from the document structure. Like the update command, it has three forms of invocation:
    1. jQuery.tmplCmd ('remove', tmplItem)
    2. jQuery.tmplCmd ('remove', tmplItems)
    3. jQuery.tmplCmd ('remove', data, tmplItems)

    The peculiarity of this command is that it not only removes rendered templates from the document structure, but also removes links to the corresponding template instances from the tmplItems array !

    This, in my opinion, is a rather unusual approach - on the one hand, it slightly reduces the effort required to maintain the tmplItems array in a consistent state, and on the other hand, it can create an unpleasant situation. Perhaps I would prefer this team to have no side effects.

    The code for deleting a table element is shown below:

    $('#items_bag').delegate('.item-delete', 'click', function () {
        var tmplItem = $.tmplItem(this);
        var dataItem = tmplItem.data;
        if (confirm('Do you really want to delete "' + dataItem.firstName + ' ' + dataItem.lastName + '"?')) {
            dataItems.splice(jQuery.inArray(dataItem, dataItems), 1);
            $.tmplCmd('remove', dataItem, tmplItems);
            updateDebugInfo();
        }
    });

    Here I first get a link to the template instance and a link to the data item:

    var tmplItem = $.tmplItem(this);
    var dataItem = tmplItem.data;

    And after receiving confirmation from the user, I first delete the corresponding element from the dataItems array :

    dataItems.splice(jQuery.inArray(dataItem, dataItems), 1);

    And then I delete the corresponding rendered template from the document structure and at the same time delete the link to the template instance from the tmplItems array :

    $.tmplCmd('remove', dataItem, tmplItems);

    The code for the updateDebugInfo () function is shown below:

    function updateDebugInfo() {
        $('#data_items_length').text(dataItems.length);
        $('#tmpl_items_length').text(tmplItems.length);
    }

    This function is just intended to demonstrate the side effect of the remove command .

    How it works is shown in the video below:



    Find command


    The find command is used to search for template instances associated with specific data. Together with the update and remove commands, it can be used to “spot” update a document when re-rendering all the templates takes too much time.

    This command allows only one form of invocation:
    1. jQuery.tmplCmd ('find', data, tmplItems)

    The result of this command is an array of links to template instances associated with the data passed through the data argument .

    An example of using the find command is given below (the full example code is in the Samples.htm file ):

    $('#item_rnd').click(function () {
        var dataItem = dataItems[Math.round(Math.random() * (dataItems.length - 1))];
        var tmplItem = $.tmplCmd('find', dataItem, tmplItems)[0];
        $(tmplItem.nodes).css('background-color', '#ff0000');
        $(tmplItem.nodes).animate({ 'background-color': '#ffffff' }, 1500);
    });

    In this example, I randomly select a data item:

    var dataItem = dataItems[Math.round(Math.random() * (dataItems.length - 1))];

    Then, using the find command, I find the template instance that this data item is associated with:

    var tmplItem = $.tmplCmd('find', dataItem, tmplItems)[0];

    And finally, I highlight the corresponding row in the table:

    $(tmplItem.nodes).css('background-color', '#ff0000');
    $(tmplItem.nodes).animate({ 'background-color': '#ffffff' }, 1500);

    In a real application, updated data can be obtained, for example, using an AJAX request.

    How it works is shown in the video below:



    Rendered event


    The rendered event is defined for the template instance and is called after the rendered template is placed in the document structure.

    To set the event handler, use the options parameter of the .tmpl () call :

    var options = {
        rendered: function (tmplItem) {
            if (window.console) {
                console.log("rendered: %s %s", tmplItem.data.firstName, tmplItem.data.lastName);
            }
        }
    };
    $('#item_tmpl').tmpl(dataItems, options).appendTo('#items_bag');

    The most obvious scenario where this event may be required is debugging. In the above example, each time a template is rendered, a message is displayed in the debug console, with the help of which it is easy to make sure that the replace command does not really re-render, and the update command from the above example updates only one row of the table.

    How it works is shown in the video below:



    Conclusion


    The full code of examples used in the article, you can download at this link .

    I also remind you that you can download jQuery Templates from the ASP.NET CDN website or directly from the GitHub repository:

    The jQuery Templates documentation is available on the jQuery documentation site .