Загрузка удаленных шаблонов jsRender (проблема с данными AJAX)

Я пытаюсь обновить веб-сайт для использования шаблонов jsRender (раньше он использовал jTemplates), и я изучаю jsRender (как сайт Бориса, так и материал, созданный Джоном Папой) и пытаюсь следовать приведенным здесь инструкциям: JSViewsRemoteLoadTemplates

Обратите внимание, что по состоянию на 13.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,"Значение": "НЕОРГАНИЧЕСКИЕ КИСЛОТЫ, НЕУТОЧНЕННЫЕ", "Транс": "НЕОРГАНИЧЕСКИЕ КИСЛОТЫ, НЕУТОЧНЕННЫЕ","Active_Flag":false},{"__type":"BLS","TreeCode":"0131","TreeType":"OBJ","ParentID":88,"Children":[],"TypeID":90,"Value":" ХЛОРИНООБРАЗУЮЩИЕ КИСЛОТЫ "," Trans ":" ХЛОРИНООБРАЗУЮЩИЕ КИСЛОТЫ "," Active_Flag " ":ложный}]}"

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>");

Некоторые конкретные заметки о том, что я узнал при реализации этого конкретного jQuery для новичков js/jsRender. Я должен был убедиться, что шаблон загружался на страницу, прежде чем он был вызван. Мне также пришлось ссылаться на data.d, когда я передавал данные в шаблон. Данные вызова не были достаточными. Я также потерял драгоценное время, когда меня смутили данные ajax и я подумал, что элементы, которые я пытался отобразить, находятся внутри массива с именем Children, что, как я обнаружил, не имело место. И последние две части, которые сделали эту работу, были в том, что я должен был установить async в true и установить dataType в "JSON". В частности, о dataType, есть еще один пост, в котором упоминается установка его "text", чтобы он работал, и с моей проблемой, которая в итоге не стала применимой, но это то, что может помочь кому-то еще в будущем. И, наконец, конкретно о самом шаблонном скрипте, мне не нужно было указывать фактическое имя элемента с помощью оператора for. Основываясь на некоторых примерах, я подумал, что мне нужно поставить {{для данных}} или {{для детей}}, но, я полагаю, потому что в конце я передал data.d, просто вызвав {{for}} было достаточно.

Первый - вы смотрели вкладку "Полный код" на странице 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}} сам по себе ничего не сделает...

Другие вопросы по тегам