【问题标题】:jsRender Loading Remote Templates (AJAX Data Issue)jsRender 加载远程模板(AJAX 数据问题)
【发布时间】:2013-11-12 19:19:23
【问题描述】:

我正在尝试升级网站以使用 jsRender 模板(它曾经使用 jTemplates)并且我一直在研究 jsRender(Boris 的网站和 John Papa 制作的材料)并尝试按照此处的说明进行操作:JSViewsRemoteLoadTemplates

请注意,截至 2013 年 11 月 13 日,此问题已被编辑以反映部分解决方案并清理内容:

经过大量实验后,我能够让 jsRender 模板处理静态数据,但是一旦我将数据更改为 ajax 源,模板就会呈现为空。我相信它可能会呈现为空,因为我没有在 .js 模板本身中指定正确的措辞,但我已经尝试了各种变体,但还没有任何效果。

我的页面是一个基本的 .htm 页面。我在标题中使用 jQuery 1.10.2、json.js 和 jsrender.min.js。这是我在页面上的脚本:

<script style='text/javascript'>
$(function () {
    lazyGetTemplate('PopupChildren');
});

function lazyGetTemplate(name) {
    var deferred = $.Deferred();
    if ($.templates[name]) {
        deferred.resolve();
    }
    else {
        $.getScript("/_Scripts/" + name + ".js").then(function () {
            if ($.templates[name]) {
                deferred.resolve();
            }
            else {
                alert("Script: \"" + name + ".js\" failed to load.");
                deferred.reject();
            }
        });
    }
}

/* This is my sample static data that jsRender works with */
var staticdata = [
{
    "TypeID": "88", "Value": "ORGANICS"
},
{
    "TypeID": "89", "Value": "SPECIFIED ORGANICS"
}
];

function getMyTemplate(data) {
    $div_Child.html($.templates.PopupChildren.render(data)); 
 //change data to staticdata to test static info, I've also set this to JSON.stringify(data) but the result is still empty
}

/* This is the ajax that calls the external function I'm using for testing */
function selItem(cControl, treeID, treeTrans) {
    var parentID = treeID;

    if ($(cControl).parent().find('ul').length == 0) {
        $.ajax({
            type: "Post",
            url: "Contractor_ws.asmx/web_getChildren",
            async: true,
            dataType: "text",
            data: "{parentID:" + parentID + ", popupType:'" + $('#hid_popupType').val() + "'}",
            contentType: "application/json",
            success: function (data) {
                if (data != null) { //menu item has children
                    $(cControl).after("<div id=\"div_Child\"></div>");
                    $div_Child = $(cControl).parent().find('#div_Child');
                    $div_Child.hide();
                    getMyTemplate(data); 
                    $div_Child.show('slow');
                }
            },
            error: function (xhr) {
                alert(xhr.responseText);
            }
        });
    }
}

</script>

PopupChildren 脚本(模板):

$.templates("PopupChildren", "<ul>{{for}}<li><a onclick='selItem(this,'{{:TypeID}}','{{:Value}}');'>{{:Value}}</a></li>{{/for}}</ul>");

示例 ajax 数据:

数据:"{"d":[{"__type":"BLS","TreeCode":"0130","TreeType":"OBJ","ParentID":88,"Children":[], "TypeID":89,"Value":"无机酸,未指定","Trans":"无机酸,未指定","Active_Flag":false},{"__type":"BLS","TreeCode":"0131 ","TreeType":"OBJ","ParentID":88,"Children":[],"TypeID":90,"Value":"含氯氧酸","Trans":"含氯氧酸" ,"Active_Flag":false}]}"

【问题讨论】:

    标签: jquery jsrender


    【解决方案1】:

    首先 - 您是否查看过 JSViewsRemoteLoadTemplates 页面上的“完整代码”标签?您可以运行该 HTML 页面作为测试和修改示例的起点

    $.when() 用于组合承诺。在你上面的例子中只有一个 - 所以你可以写(不使用$.when):

    function getMyTemplate() {
        lazyGetTemplate("PopupChildren")
            .done(function () {
                var html = $.templates.PopupChildren.render(data);
                $div_Child.html(html);
             });
    }
    

    但要使您的模板正常工作,当前语法是 {{if ...}} {{/if}}{[for ...}} 也是如此。

    {{#if ...}} {{#/if}} 不正确。 (另外你还有一个+:'{{#/if}}' + );

    在您的简化模板中,您应该写{{for Children}} - 我假设。 {{for}} 本身不会做任何事情...

    【讨论】:

    • 嗨,鲍里斯,我取得了一些进展,并在上面发布了对我的问题的重大修订,因此我之前的一些问题不再适用。您对为什么不读取 ajax 有任何想法吗?
    • 你仍然有没有参数的 {{for}} - 这不应该迭代孩子吗?
    • 只是想感谢您的耐心并帮助我解决此问题。
    【解决方案2】:

    我找到了我遇到的问题的解决方案,它结合了我调用模板的方式和在 ajax 中设置的参数。这是对我有用的解决方案:

    $(function () { /* js ready function */
        lazyGetTemplate('PopupChildren');
    });
    
    /* this is the function that loads the template from the script */
    function lazyGetTemplate(name) {
       var deferred = $.Deferred();
       if ($.templates[name]) {
           deferred.resolve();
       }
       else {
        $.getScript("/_Scripts/" + name + ".js").then(function () {
            if ($.templates[name]) {
                deferred.resolve();
            }
            else {
                alert("Script: \"" + name + ".js\" failed to load.");
                deferred.reject();
            }
        });
       }
     }
    
    /* this is the ajax calling my additional items for display */
    function selItem(cControl, treeID, treeTrans) {
    var parentID = treeID;
    
    if ($(cControl).parent().find('ul').length == 0) {
        $.ajax({
            type: "Post",
            url: "Contractor_ws.asmx/web_getChildren",
            async: true, 
            dataType: "JSON",
            data: "{parentID:" + parentID + ", popupType:'" + $('#hid_popupType').val() + "'}",
            contentType: "application/json",
            success: function (data) {
                if (data != null) { //menu item has children
                    $(cControl).after("<div id=\"div_Child\"></div>");
                    $div_Child = $(cControl).parent().find('#div_Child');
                    $div_Child.hide();
                    var myData = data.d;
                    $div_Child.html($.templates.PopupChildren.render(myData));
                    $div_Child.show('slow');
                }
            },
            error: function (xhr) {
                alert(xhr.responseText);
            }
        });
      }
    }
    
    /* this is the content of the actual script that gets called from the lazyGetTemplate() */
    $.templates("PopupChildren", "<ul>{{for}}<li><a onclick=\"selItem(this,\'{{:TypeID}}\',\'{{:Value}}\');\">{{:Value}}</a>{{/for}}</ul>");
    

    关于我在为 js/jsRender 新手实现这个特定的 jQuery 时学到的一些具体说明。在调用模板之前,我必须确保模板已加载到页面上。当我将数据传递给模板时,我还必须引用“data.d”。调用数据是不够的。当我对 ajax 数据感到困惑时,我还浪费了一些宝贵的时间,并认为我试图显示的项目位于一个名为 Children 的数组中,我发现事实并非如此。完成这项工作的最后两部分是我必须将 async 设置为 true,并且必须将 dataType 设置为“JSON”。特别是关于数据类型,还有另一篇文章提到将其设置为“文本”以使其工作,并且我的问题最终并不适用,但它可能会在未来帮助其他人。最后,特别是关于模板脚本本身,我不必在 for 语句中列出实际的项目名称。根据我看到的一些示例,我认为我需要放置 {{for data}} 或 {{for Children}} 但是,我假设,因为我最后传递了 data.d,只需调用 {{for} } 就足够了。

    【讨论】:

    • 如果您针对 myData 进行渲染,它是一个数组(data.d,对吗?),那么您的模板将为数组中的每个项目渲染一次,{{for}} 将执行什么都没有,所以您将渲染
      • ...
      • ...
      ... 如果您改为渲染数据,您可以编写
        {{for d}}
      • ... 它将仅针对数组 d 迭代
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多