jquery-tmpl icon indicating copy to clipboard operation
jquery-tmpl copied to clipboard

Calling $.tmpl().appendTo during rendering of another template breaks tmplItem

Open Gedis opened this issue 15 years ago • 8 comments

after updating tmplItem of the nested template, where {{html MyFunction( 'test' )}} are used, nodes attribute of the tmplItem is [] - expected updated DOM. Before update() call nodes carried DOM, after update, which enabled branch with the {{html MyFunction.... }}, nodes became empty

in some cases data attribute is empty, although nodes isn't, using plugin version for the jQuery 1.4.4

Gedis avatar Feb 01 '11 13:02 Gedis

Bug test case example:

templates:

    <script id="PlacesTemplate" type="text/x-jquery-tmpl"> 
        <div title="${Place}">${Place}</div>                       
        <select name="options">{{html GetOptions()}}</select>
    </script>                

HTML:

Result:



JS: function OuterHTML( data$ ) { return data$.wrapAll( '

' ).parent().html(); }
GetOptions = function( data$ )
{
    return OuterHTML( $( '#selectOptionsTemplate' ).tmpl( _options ) );
}

_options = { Items : [ { key : 1, value : "one" }, { key : 2, value : "two" }, { key : 3, value : "three" }] };
_data = { Name : "Tom", Places : [ { Id : 1, Place : 'London' }, { Id : 3, Place : 'Berlin' }, { Id : 5, Place : 'Brno' } ] };

$( ':button' ).click( function( event )
{
    var _templateItem$ = $.tmplItem( $( 'div[title=Brno]' ) );
    _templateItem$.data.Place = 'newPlace';
    _templateItem$.update();
});

$( '#TestTemplate' ).tmpl( _data ).appendTo( 'body #Result');

After clicking button, Brno changes into newPlace and $.tmplItem( $( 'div[title=newPlace]' ) ) object's data = {}, parent = null and tmpl = null, although before template update $.tmplItem( $( 'div[title=Brno]' ) ) object's data = { Id : 5, Place : Brno } and parent pointed to the TestTemplate template item object.

Gedis avatar Feb 08 '11 09:02 Gedis

The above seems incomplete. For example, there is no selectOptionsTemplate. A complete HTML page would allow me to see more of what you might be doing here.

But if I modify the page so it can run I get the following, and the code runs correctly. The _templateItem$ has nodes and parent, tmpl are not null after update:

<div>
    Result:</div>
<button name="UpdatePlace">
    Change place</button>
<div id="Result">
</div>
<script id="TestTemplate" type="text/x-jquery-tmpl"> 
    <div title="${Name}">${Name}</div>            
    {{each Places}}
        {{tmpl( $value ) "#PlacesTemplate"}}            
    {{/each}}
</script>
<script id="PlacesTemplate" type="text/x-jquery-tmpl"> 
    <div title="${Place}">${Place}</div>                       
</script>
<script>


    _options={ Items: [{ key: 1,value: "one" },{ key: 2,value: "two" },{ key: 3,value: "three"}] };
    _data={ Name: "Tom",Places: [{ Id: 1,Place: 'London' },{ Id: 3,Place: 'Berlin' },{ Id: 5,Place: 'Brno'}] };

    $(':button').click(function (event) {
        var _templateItem$=$.tmplItem($('div[title=Brno]'));
        _templateItem$.data.Place='newPlace';
        _templateItem$.update();

    });

    $('#TestTemplate').tmpl(_data).appendTo('body #Result');</script>

BorisMoore avatar Feb 09 '11 23:02 BorisMoore

Closing, since this works fine for me.

BorisMoore avatar Feb 09 '11 23:02 BorisMoore

doesn't work - at least for me, took the screenshot after clicking the button ( $.tmplItem( $( '[title=newPlace]' ) ) command): http://img717.imageshack.us/i/templateupdatebug.png/

I am sorry, left selectOptionsTemplate, so this is the complete code: HTML:

<head>
    <script type="text/javascript" src="jquery-1.4.4.min.js"></script>
    <script type="text/javascript" src="jquery.tmpl.js"></script>               
    <script type="text/javascript" src="test2.js"></script>

    <script id="selectOptionsTemplate" type="text/x-jquery-tmpl"> 
        {{each Items}}
            <option value="${key}">${value}</option>
        {{/each}}
    </script>        

    <script id="TestTemplate" type="text/x-jquery-tmpl"> 
        <div title="${Name}">${Name}</div>            
        {{each Places}}
            {{tmpl( $value ) "#PlacesTemplate"}}            
        {{/each}}
    </script>        

    <script id="PlacesTemplate" type="text/x-jquery-tmpl"> 
        <div title="${Place}">${Place}</div>                       
        <select name="options">{{html GetOptions()}}</select>
    </script>                         
</head>    

<body>
    <div>Result:</div>        
    <button name="UpdatePlace">Change place</button>        
    <div id="Result"></div>    
</body>    

JS: $(document).ready(function() {
function OuterHTML( data$ ) { return data$.wrapAll( '

' ).parent().html(); }
GetOptions = function()
{
    return OuterHTML( $( '#selectOptionsTemplate' ).tmpl( _options ) );
}

_options = { Items : [ { key : 1, value : "one" } ] };
_data = { Name : "Tom", Places : [ { Id : 5, Place : 'Brno' } ] };

$( ':button' ).click( function( event )
{
    var _templateItem$ = $.tmplItem( $( 'div[title=Brno]' ) );
    _templateItem$.data.Place = 'newPlace';
    _templateItem$.update();
});

$( '#TestTemplate' ).tmpl( _data ).appendTo( 'body #Result');   

} );

Gedis avatar Feb 10 '11 07:02 Gedis

can everybody perform this test case - I have uploaded all needed files (html, javascript, jquery, templates) in two storages: http://uploading.com/files/med2165c/test2.7z/ and http://depositfiles.com/files/98zgdiolp

load test2.html and execute $.tmplItem( $( 'div[title=Brno]' ) ) command (I get in firebug object taken in http://img829.imageshack.us/i/beforeupdate.png/), click "Change place" button and then execute $.tmplItem( $( 'div[title=newPlace]' ) ) command (I get object in http://img202.imageshack.us/i/afterupdate.png/).

Is the result you got the same as I getting? Notice the data, parent and tmpl keys change in the result object. After template update (line 21 in test2.js) data becomes {}, parent - null and tmpl - null.

Tested in Firefox 3.6.13 (official build) and jQuery 1.4.4. Tested on several windows machines with the same consistent output

Gedis avatar Feb 17 '11 12:02 Gedis

I have reopened, and changed the title. We currently don't support using template rendering in code that is itself called as part of rendering a template. Your GetOptions is doing that. I hope to fix this, and also provide better APIs for rendering a template to a string, in Beta2, due in April.

Repro for this issue:

<script id="myTmpl" type="text/x-jquery-tmpl"> 
    <div id="test">${getFoo()}</div>
</script>

<div id="result"></div>    

<script type="text/javascript">
    function getFoo()
    {
        $.tmpl( "<b></b>", {} ).appendTo($("<div></div>"));
        return 'foo';
    }

    function update()
    {
        var ti = $( '#test' ).tmplItem();
        ti.update();
        alert( $('#test').tmplItem() === ti );
    };

    $( '#myTmpl' ).tmpl().appendTo( '#result');
</script>

<button onclick="update()">Update</button>

BorisMoore avatar Feb 17 '11 18:02 BorisMoore

BTW you don't need to do the complicated code for building your options HTML. Just do:

<select>{{tmpl(_options) '#selectOptionsTemplate'}}</select>

rather than

<select>{{html GetOptions()}}</select>

BorisMoore avatar Feb 17 '11 19:02 BorisMoore

Thanks for taking the time to submit this issue. Just wanted to let you know this plugin is no longer being actively developed or maintained by the jQuery team. See README for more info.

rdworth avatar Oct 08 '11 06:10 rdworth