locked
Template Binding, possible clousure issue? RRS feed

  • Question

  • Hi Guys,

    I am trying to bind template as mentioned in blog "http://stephenwalther.com/archive/2012/02/27/metro-using-templates.aspx".

    WinJS.UI.Pages.define("/html/schedule.html", {
            ready: function (targetElement) {
                var myTest = [{ field1: 'Hello1', field2: 'Hello2' },
                              { field1: 'Hello3', field2: 'Hello4' }];
                        
                var template = new WinJS.Binding.Template(null, { href: "/templates/schedule/playgroundtemplate.html" });
                var targetElement = document.getElementById("myTest");
    
                var a, x;
                for (var i = 0; i < myTest.length; i++) {
                    x = myTest[i];
                    template.render(x, targetElement);
                    
                }
            }
        });

    Below is template

    <html>
        <head><title>template</title></head>
        <body>
            <div style="border: 1px solid red;">
                <h2 data-win-bind="innerText: field1"></h2>
            </div>
            <div style="border: 1px solid green;">
                <h4 data-win-bind="innerText: field2"></h4>
            </div>
        </body>
    </html>

    And below is screenshot of how it looks like after binding.

    Any idea why would it behave like that? I already tried self executing function and passing array element as parameter as well as trying different scopes for parameter and no results. I am wondering am I missing something here?

    Regards.


    Tuesday, July 24, 2012 4:27 PM

Answers

  • It appears that you've found a bug in the template control!

    The bug probably has something to do with the fact that loading and parsing the template from an external HTML file is async, and multiple calls to render before that happens aren’t being queued up properly.

    The best way I can think to fix it is to not put your templates in a bunch of different HTML files. First to avoid this bug, and second because it’s probably faster to have all your templates processed and on-hand as the app is loading.

    What I do is create a hidden section of default.html to hold my templates, and then I can get them by ID when I need to render them:

    <body>
        <div id="myTest"></div>
        <div style="display: none">
            <!-- templates go in this div -->
            <div id="playgroundTemplate" data-win-control="WinJS.Binding.Template">
                <div style="border: 1px solid red;">
                    <h2 data-win-bind="innerText: field1"></h2>
                </div>
                <div style="border: 1px solid green;">
                    <h4 data-win-bind="innerText: field2"></h4>
                </div>
            </div>
        </div>
    </body>

    function ready() {
        var myTest = [{ field1: 'Hello1', field2: 'Hello2' },
                      { field1: 'Hello3', field2: 'Hello4' }];
    
        var targetElement = document.getElementById("myTest");
    
        // Assumes WinJS.UI.processAll was completed during onactivated.
        var template = document.getElementById("playgroundTemplate").winControl;
    
        var a, x;
        for (var i = 0; i < myTest.length; i++) {
            x = myTest[i];
            template.render(x, targetElement);
        }
    };


    Tuesday, July 24, 2012 5:22 PM

All replies

  • It appears that you've found a bug in the template control!

    The bug probably has something to do with the fact that loading and parsing the template from an external HTML file is async, and multiple calls to render before that happens aren’t being queued up properly.

    The best way I can think to fix it is to not put your templates in a bunch of different HTML files. First to avoid this bug, and second because it’s probably faster to have all your templates processed and on-hand as the app is loading.

    What I do is create a hidden section of default.html to hold my templates, and then I can get them by ID when I need to render them:

    <body>
        <div id="myTest"></div>
        <div style="display: none">
            <!-- templates go in this div -->
            <div id="playgroundTemplate" data-win-control="WinJS.Binding.Template">
                <div style="border: 1px solid red;">
                    <h2 data-win-bind="innerText: field1"></h2>
                </div>
                <div style="border: 1px solid green;">
                    <h4 data-win-bind="innerText: field2"></h4>
                </div>
            </div>
        </div>
    </body>

    function ready() {
        var myTest = [{ field1: 'Hello1', field2: 'Hello2' },
                      { field1: 'Hello3', field2: 'Hello4' }];
    
        var targetElement = document.getElementById("myTest");
    
        // Assumes WinJS.UI.processAll was completed during onactivated.
        var template = document.getElementById("playgroundTemplate").winControl;
    
        var a, x;
        for (var i = 0; i < myTest.length; i++) {
            x = myTest[i];
            template.render(x, targetElement);
        }
    };


    Tuesday, July 24, 2012 5:22 PM
  • Thanks Bryan !! Appreciate that. Sole purpose of us using this approach was separating reusable views. But meanwhile you guys fix it we will use workaround. Only surprise I have is how come it is working for Stephen as mentioned in his blog "http://stephenwalther.com/archive/2012/02/27/metro-using-templates.aspx".
    Tuesday, July 24, 2012 6:10 PM
  • Okay, the product team now knows about the bug. Good catch, thank you!

    If you want to keep loading your templates that way they offered this workaround:

    WinJS.UI.Pages.define("/html/schedule.html", {

            ready: function (targetElement) {

                var myTest = [{ field1: 'Hello1', field2: 'Hello2' },

                              { field1: 'Hello3', field2: 'Hello4' }];

                       

                var template = new WinJS.Binding.Template(null, { href: "/templates/schedule/playgroundtemplate.html" });

                var targetElement = document.getElementById("myTest");

                return template.render({}).then(function() {

                    var a, x;

                    for (var i = 0; i < myTest.length; i++) {

                        x = myTest[i];

                        template.render(x, targetElement);

                        

                    }

                });

            }

        });


    Although, in my opinion, this way is a bit hacky and not as zippy. Up to you, obviously.  :)

    Tuesday, July 24, 2012 8:50 PM
  • Thanks for this!

    Though it is a bit hacky, it does sound like the bug will be resolved in the future, so this approach makes sense for our needs. We would really like to be reusing many of our views/templates throughout our app.


    • Edited by CES4848 Wednesday, July 25, 2012 11:54 AM
    Wednesday, July 25, 2012 11:53 AM
  • Thanks Bryan !! Appreciate workaround.


    Wednesday, July 25, 2012 1:39 PM
  • Hi, has this bug been fixed?  Generally, is there a list of bugs we can see?

    Thanks

    Tuesday, November 20, 2012 9:40 AM