Загрузка удаленных шаблонов 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}}
сам по себе ничего не сделает...