I am trying to load different templates in a for loop in a jsrender template.
I have tried different syntax but with no success. I have tried loading the template within a {{for fields tmpl="helperMethod()"}} and include within the loop as well. But no success till now.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrender/1.0.5/jsrender.js"></script>
<script type="text/javascript" src="form.js"></script>
<title>Insert title here</title>
</head>
<body>
<div id="formbody">
</div>
<form name="submit()">
<input name = "nitin" value="" placeholder="Put name">
<input name = "password" value="" placeholder="Put password" type='password'>
</form>
</body>
</html>
<script id="formTemplate" type="text/x-jsrender">
<form id={{:id}}>
{{for steps tmpl="#stepTemplate"}}
{{/for}}
</form>
</script>
<script id="stepTemplate" type="text/x-jsrender">
<div id={{:id}} data-order={{:order}}>
<span><h2>{{:title}}</h2></span>
<div id="dynamic-field-div">
{{for fields tmpl="#"+~loadTemplate(:mytype)/}}
</div>
</div>
</script>
<script id="field-input-template" type="text/x-jsrender">
<span>{{:type}}</span>
<span>{{:templateOptions.label}}</span>
<input name = {{:key}} id={{:id}} field-order={{:#index}} {{if templateOptions.hint != null && templateOptions.hint != "" }} placeHolder={{:templateOptions.hint}} {{/if}}>
</script>
<script id="field-password-template" type="text/x-jsrender">
<span>{{:label}}</span>
<input name = {{:key}} id={{:id}} field-order={{:#index}} type="password">
</script>
$(document).ready(function(){
var formDescription = {
"id":"loginForm",
"steps": [
{
"id": "step_0",
"order": 0,
"title": "Personal Details",
"fields": [
{
"key": "firstName",
"templateOptions": {
"label": "First Name",
"hint": "enter first name"
},
"mytype":"input"
},
{
"key": "lastName",
"templateOptions": {
"label": "Last Name"
},
"mytype":"password"
}
]
},
{
"id": "step_1",
"order": 1,
"title": "Business Details",
"fields": [
{
"key": "email",
"templateOptions": {
"label": "First Name",
"hint": "input first name"
},
"mytype":"input"
},
{
"key": "mobile",
"templateOptions": {
"label": "Last Name",
"hint": "input last name"
},
"mytype":"password"
}
]
}
]
};
var templateObjects = $.templates({
stepTmpl: "#stepTemplate",
formTmpl: "#formTemplate"
});
function loadTemplateFromType(type) {
console.log(type);
return "field-"+type+"-template";
}
var myHelpers = {"loadTemplate": loadTemplateFromType};
$.views.helpers(myHelpers);
function appendToDom() {
$('#formbody').append(generateFormHTML());
}
function generateFormHTML() {
console.log("in generate");
var formHtml = $.render.formTmpl(formDescription);
return formHtml;
}
appendToDom();
});
This is the error message that I can see on console.
message
:
"Syntax error↵Compiled template code:↵↵// stepTmpl↵var v,t=j._tag,ret=""↵+"\n<div id=";↵try{↵ret+=((v=data.id)!=null?v:"");↵}catch(e){ret+=j._err(e,view,undefined);}ret=ret↵+" data-order=";↵try{↵ret+=((v=data.order)!=null?v:"");↵}catch(e){ret+=j._err(e,view,undefined);}ret=ret↵+">\n <span><h2>";↵try{↵ret+=((v=data.title)!=null?v:"");↵}catch(e){ret+=j._err(e,view,undefined);}ret=ret↵+"</h2></span>\n <div id=\"dynamic-field-div\">\n ";↵try{↵ret+=t("for",view,this,[↵{view:view,content:false,tmpl:false,↵ params:{args:['fields'],↵ props:{'tmpl':'\"#\"+~loadTemplate(:mytype)'}},↵ args:[data.fields],↵ props:{'tmpl':"#"+view.ctxPrm("loadTemplate")(:data.mytype)}}]);↵}catch(e){ret+=j._err(e,view,undefined);}ret=ret↵+"\n </div>\n</div>\n";↵return ret;↵: "Unexpected token :""
name:"JsRender Error"
}
The for loop in the "stepTemplate" in the index.html in the contentious code. If I remove the ":" from the ":mytype" then it just prints the expression in the browser .
The problem is with
{{for fields tmpl="#"+~loadTemplate(mytype)/}}
which will use the template returned by ~loadTemplate(mytype)
, and iterate over the fields using that template. You want to iterate over the fields, and use a different template for each field, based on the mytype
value on the field object.
You can do it like this:
{{for fields}}{{include tmpl="#"+~loadTemplate(mytype)/}}{{/for}}