WebApp templates
WebApps use underscore templates. Templates are initially rendered server side and will be delivered to the client as HTML when the page loads. If the WebApp needs to be re-rendered, it will render client side using the same template. Templates are .html
files stored in the /template
folder.
Rendering a template
A component is responsible for setting a template. Either by using the template
property or the getTemplate
function.
template
Sets the template for the component.
getTemplate
Function for calculating which template to render
renderTemplate(template [, options])
Renders a template.
// using template property
define(function(require) {
'use strict';
var
Component = require('Component'),
indexTemplate = require('/template/index');
return Component.extend({
template: indexTemplate
});
});
// using getTemplate function
define(function(require) {
'use strict';
var
Component = require('Component'),
listTemplate = require('/template/list'),
gridTemplate = require('/template/grid');
return Component.extend({
getTemplate: function() {
if (this.state.layout === 'list') {
return listTemplate;
}
return gridTemplate;
}
});
});
Rendering sub components
Rendering will always start from the template referenced in main.js. Most WebApps are split into different components and defining sub components is handled by the renderer.renderComponent
function available in the template context.
renderer.renderComponent(componentName [, options])
Renders a sub component. componentName
refers to the name of the component to render (the name of the file in the /component folder).
// template referenced from main.js
<h1>Hello from main template</h1>
// render a sub component
<%= renderer.renderComponent('MySubComponent') %>
Rendering sub component with properties [@since 6.1]
When rendering sub components it is possible to pass properties to the component. Properties will be available on this.options
and passed in as second parameter to filterState
.
// render a sub component
<%= renderer.renderComponent('MySubComponent', {foo: 'bar'}) %>
// MySubComponent.js
define(function(require) {
'use strict';
var Component = require('Component');
return Component.extend({
onRendered: function() {
console.log(this.options.foo); // 'bar'
},
filterState: function(state, options) {
// options -> {foo: 'bar'}
return Object.assign({}, state);
}
});
});
Template context
A component's state (collected from the filterState
function) is always available in the template context. Use underscore template syntax to print values.
// this.state.buttonText --> 'Click me!';
<button><%- buttonText %></button> // <button>Click me!</button>
Template context may be extended using the templateFunctions
helper for the rendering component.
templateFunctions (may be defined as a function)
Extend template context with custom functions and data.
define(function(require) {
'use strict';
var
Component = require('Component'),
indexTemplate = require('/template/index');
return Component.extend({
template: indexTemplate,
templateFunctions: function() {
return {
foo: 'bar',
getPrice: function(price, vatRate) {
return price * vatRate;
}
};
}
});
});
// index.html
<span><%- foo %></span> // bar
<span><%- getPrice(100, .25) %></span> // 25
Methods
getUrl(path [, queryStringParameters])
Returns a WebApp specific url given a path.
Pass an object as queryStringParameters
to retrieve a url with given query string parameters.
// returns a URL that will match the /addToBasket path in index.js
<form action="<%= getUrl('/addToBasket') %>" method="post">
// ?sv.target=<id>&sv.<id>.route=/addToBasket
// update only query string
<a href="<%= getUrl('/', {layout: 'grid'}) %>">
// ?sv.target=<id>&sv.<id>.route=/&layout=grid
getStandaloneUrl(path [, queryStringParameters]) [@since 4.5.5]
Returns a url that will execute a route standalone, i.e. it will not be part of page rendering. This is very useful when you only want to target your route without any side effects. Typical use cases are delivering a file from a route or redirecting when a form has been posted.
Below is an example demonstrating aforementioned use cases.
<form action="<%= getStandaloneUrl('/ship') %>" method="post">
<input type="text" name="text">
<button type="submit">Submit</button>
</form>
<a href="<%- getStandaloneUrl('/file') %>">Get file</a>
// index.js
router.post('/ship', (req, res) => {
// Handling the posted form data in req.params...
res.redirect('back');
});
router.get('/file', (req, res) => {
const file = appData.getNode('file');
res.sendFile(file);
});
getResourceUrl(path)
Returns a url to a resource within the WebApp's /resource folder.
<img src="<%- getResourceUrl('image.png') %>" />
/webapp-files/<webappname>/<webappversion>/image.png
i18n(key [, varSubstitution...])
Returns localized string from bundles in the /i18n
folder.
<h2><%- i18n('hello') %></h2>
appContext.getWebAppNamespace(prefix)
Returns a prefixed unique namespace for the WebApp. Useful when there are several instances of the same WebApp on the same page.
<input id="<%- appContext.getWebAppNamespace('query') %>">