jsRender加载远程模板(AJAX数据问题)

时间:2013-11-12 19:19:24

标签: jquery jsrender

我试图升级网站以使用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数据:

数据:&#34; {&#34; d&#34;:[{&#34; __ type&#34;:&#34; BLS&#34;,&#34; TreeCode&#34;:&# 34; 0130&#34;&#34; TreeType&#34;:&#34; OBJ&#34;&#34; PARENTID&#34;:88,&#34;儿童&#34;:[],&# 34; TypeID&#34;:89,&#34;价值&#34;:&#34;无机酸,未检测&#34;,&#34; Trans&#34;:&#34;无机酸,未发现&#34; &#34; Active_Flag&#34;:假},{&#34; __类型&#34;:&#34; BLS&#34;&#34; TreeCode&#34;:&#34; 0131&#34 ;, &#34; TreeType&#34;:&#34; OBJ&#34;&#34; PARENTID&#34;:88,&#34;儿童&#34;:[],&#34; TYPEID&#34 ;: 90,&#34;价值&#34;:&#34;含氯的氧化物&#34;,#34; Trans&#34;:&#34;含氯的氧化物&#34;,&#34;,Active_Flag&# 34;:假}]}&#34;

2 个答案:

答案 0 :(得分:0)

首先 - 您是否查看了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}}本身不会做任何事......

答案 1 :(得分:0)

我找到了我遇到的问题的解决方案,它是我如何调用模板和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”。特别是关于dataType,还有另一篇文章提到将其设置为“文本”以使其正常工作,并且我的问题并非最终适用,但它可能在将来帮助其他人。最后,特别是关于模板脚本本身,我没有用for语句列出实际的项目名称。我认为基于我看到的一些例子,我需要放置{{for data}}或{{for Children}}但是,我假设,因为我最后传递了data.d,只是调用了{{for}已经足够了。