使用从 ajax 响应生成的 handlebars.js 模板
Consuming handlebars.js template generated from ajax response
handlebars.js 模板在服务器端生成并作为响应的一部分返回。
"<div>{{name}}<small style='color:#999;'><br><code>{{vafm}}</code></small><br><code>{{email}}</code></div>"
.
var t = "";
$('#UniqueId').select2({
ajax: {
url: '/search/endpoint',
dataType: 'json',
processResults: function (data) {
t = data.template;
return {
results: data.results
};
},
},
templateResult: Handlebars.compile(t),
escapeMarkup: function (m) {
return m;
}
});
不幸的是 select2 上的渲染部分不包含 data.results
返回的值
我已将问题定位到这一行
templateResult: Handlebars.compile(t),
自从尝试了
<script>
const template = Handlebars.compile(@Html.Raw(Model.Template));
</script>
和
templateResult: template,
按预期工作。
在最后一个例子中,我从模型中传递了模板,
但我不需要从 ajax 响应中传递它并获得相同的输出。
存在多个问题:
templateResult
需要回调函数,但您传递的是已编译的 Handlebars 模板对象。 the select2 docs 中对此进行了描述。因此,假设您已经在正确的位置执行了以下操作:
var t = Handlebars.compile(...)
然后像这样的东西会起作用:
templateResult: function(data) {
if (!data.id) return data.text;
return $(t({
name: 'example name',
vafm: 'example vafm',
email: 'example email'
}));
模板html必须有一个封闭元素,所以把东西放在<div></div>
中,例如
您的模板缺少 <small>
开始标记
所以让我们假设您的服务器发送一些 JSON 如下所示。每个结果的模板都会一起发送,并且每个结果都可以不同。特定于模板的数据也是如此:
[
{
"id": 1,
"text": "Henry",
"data": {
"vafm": "1234",
"email": "henry@example.com"
},
"template": "<div>{{text}}<br><small>vafm: {{data.vafm}}</small></div><small>email: {{data.email}}</small>"
}, {
"id": 30,
"text": "Tesla Roadster",
"data": {
"price": "0.000",
"color": "dark red"
},
"template": "<div>{{text}}<br><small>price: {{data.price}}</small></div><small>color: {{data.color}}</small>"
}
]
在您的 JavaScript 中加上类似的东西,它应该可以工作:
$('#UniqueId').select2({
ajax: {
url: '/search/endpoint',
dataType: 'json',
processResults: function(data) {
/** Note: select2 expects "results" to be an array of objects, each containing
* at least "id" (becomes the value) and "text" (displayed text). I made the
* format from the server match that (plus added some more info), so that I don't
* need any conversions except for compiling the template. I do that with
* Array.prototype.map() in this case, but of course a for-loop would work too.
*/
return {
results: data.map(function(e) {
e["template"] = Handlebars.compile(e["template"]);
return e;
})
};
}
},
templateResult: function(el) {
if (!el.id) return el.text;
/* Note: "el" will be just like it came from the server, except for the
* modifications we applied in processResults. We can just pass "el" to
* the compiled template entirely and there, only pick what we need.
*/
return $(el["template"](el));
}
});
handlebars.js 模板在服务器端生成并作为响应的一部分返回。
"<div>{{name}}<small style='color:#999;'><br><code>{{vafm}}</code></small><br><code>{{email}}</code></div>"
.
var t = "";
$('#UniqueId').select2({
ajax: {
url: '/search/endpoint',
dataType: 'json',
processResults: function (data) {
t = data.template;
return {
results: data.results
};
},
},
templateResult: Handlebars.compile(t),
escapeMarkup: function (m) {
return m;
}
});
不幸的是 select2 上的渲染部分不包含 data.results
返回的值
我已将问题定位到这一行
templateResult: Handlebars.compile(t),
自从尝试了
<script>
const template = Handlebars.compile(@Html.Raw(Model.Template));
</script>
和
templateResult: template,
按预期工作。
在最后一个例子中,我从模型中传递了模板,
但我不需要从 ajax 响应中传递它并获得相同的输出。
存在多个问题:
templateResult
需要回调函数,但您传递的是已编译的 Handlebars 模板对象。 the select2 docs 中对此进行了描述。因此,假设您已经在正确的位置执行了以下操作:
var t = Handlebars.compile(...)
然后像这样的东西会起作用:
templateResult: function(data) {
if (!data.id) return data.text;
return $(t({
name: 'example name',
vafm: 'example vafm',
email: 'example email'
}));
模板html必须有一个封闭元素,所以把东西放在
<div></div>
中,例如您的模板缺少
<small>
开始标记
所以让我们假设您的服务器发送一些 JSON 如下所示。每个结果的模板都会一起发送,并且每个结果都可以不同。特定于模板的数据也是如此:
[
{
"id": 1,
"text": "Henry",
"data": {
"vafm": "1234",
"email": "henry@example.com"
},
"template": "<div>{{text}}<br><small>vafm: {{data.vafm}}</small></div><small>email: {{data.email}}</small>"
}, {
"id": 30,
"text": "Tesla Roadster",
"data": {
"price": "0.000",
"color": "dark red"
},
"template": "<div>{{text}}<br><small>price: {{data.price}}</small></div><small>color: {{data.color}}</small>"
}
]
在您的 JavaScript 中加上类似的东西,它应该可以工作:
$('#UniqueId').select2({
ajax: {
url: '/search/endpoint',
dataType: 'json',
processResults: function(data) {
/** Note: select2 expects "results" to be an array of objects, each containing
* at least "id" (becomes the value) and "text" (displayed text). I made the
* format from the server match that (plus added some more info), so that I don't
* need any conversions except for compiling the template. I do that with
* Array.prototype.map() in this case, but of course a for-loop would work too.
*/
return {
results: data.map(function(e) {
e["template"] = Handlebars.compile(e["template"]);
return e;
})
};
}
},
templateResult: function(el) {
if (!el.id) return el.text;
/* Note: "el" will be just like it came from the server, except for the
* modifications we applied in processResults. We can just pass "el" to
* the compiled template entirely and there, only pick what we need.
*/
return $(el["template"](el));
}
});