Templates para listas sin templates engines
@ JavaScript @ Permalink
Debo admitir que siempre me ha resultado pesado y aburrido integrar recursos no programados por mí en mi stack de trabajo, por eso muchas de las funciones y utilidades son de mi autoría.
Hace algún tiempo fuimos contratados por un cliente para la creación de un proyecto que requería panel para creación y actualización de contenido, aplicación para móviles y aplicación para web. Uno de los puntos fuertes de este proyecto eran las listas puesto que involucraba catálogo de productos.
Estuve revisando varios templates engines para el front-end, entre ellos EJS, mi favorito cuando desarrollo para NodeJS. Probe varios más que desconocía pero todos coincidian en el mismo punto: Ofrecían muchísimo más de lo que necesitaba.
De ahí nació xTemplateDOM, una función escrita en JavaScript vanilla:
function xTemplateDOM (parms)
{
var template_selector = parms['template_selector'] || '';
var template_string = parms['template_string'] || '';
var data = parms['data'] || [];
var htm = '', tpl = '';
data = (Array.isArray(data)) ? data : [data];
if ( (template_string || template_selector) && (data.length > 0) )
{
if ( template_string )
{
tpl = String(template_string).replace(/(\r\n|\n|\r|\s+)/gm,' ');
} else {
tpl = String(document.querySelector(template_selector).innerHTML).replace(/(\r\n|\n|\r|\s+)/gm,' ');
};
tpl = tpl.replace(/(@\{)\s*(\S+)\s*(?=})/img,'$1$2');
for (var i = 0, c = data.length; i < c; i++)
{
var row = data[i], str = tpl;
for (var k in row)
{
var key = k, val = row[k];
var rgx = new RegExp('@{' + key + '}','img');
str = str.replace(rgx,val);
};
htm += str + '\n';
};
};
return htm;
};
Integrarla en el proyecto es de lo más sencillo. Agregamos la porción del template como parte del DOM pero escondido con un script
tag:
<!DOCTYPE html>
<html>
<head>
<title>My xTemplateDOM test</title>
</head>
<body>
<ul id="box">
...
</ul>
<script type="text/templatedom" id="template-profile">
<li data-profileid="@{profileid}">
<div>
<span>Firstname:</span>
<span>@{firstname}</span>
</div>
<div>
<span>Lastname:</span>
<span>@{lastname}</span>
</div>
</li>
</script>
</body>
</html>
Finalmente llamamos el template y lo alimentamos con la data de nuestra lista:
var actors = [
{
profileid: 3321,
firstname: 'Bruce',
lastname: 'Willis'
},
{
profileid: 4318,
firstname: 'Angelina',
lastname: 'Jolie'
},
{
profileid: 7269,
firstname: 'Robert',
lastname: 'De Niro'
}
];
document.querySelector('#box').innerHTML = xTemplateDOM({
template_selector: '#template-profile',
data: actors
});
También podemos pasar el template como parte de la llamada sin necesidad de tocar el DOM:
var actors = [
{
profileid: 3321,
firstname: 'Bruce',
lastname: 'Willis'
},
{
profileid: 4318,
firstname: 'Angelina',
lastname: 'Jolie'
},
{
profileid: 7269,
firstname: 'Robert',
lastname: 'De Niro'
}
];
document.querySelector('#box').innerHTML = xTemplateDOM({
template_string: '<li data-profileid="@{profileid}">@{firstname} @{lastname}</li>',
data: actors
});
Además de lista de objetos también podemos pasar la data de solo un objecto. Es obvio, porque no todo el tiempo necesitamos alimentar listas.
document.querySelector('#box').innerHTML = xTemplateDOM({
template_selector: '#template-profile',
data: {
profileid: 7269,
firstname: 'Robert',
lastname: 'De Niro'
}
});
document.querySelector('#box').innerHTML = xTemplateDOM({
template_string: '<li data-profileid="@{profileid}">@{firstname} @{lastname}</li>',
data: {
profileid: 7269,
firstname: 'Robert',
lastname: 'De Niro'
}
});
Creo xTemplateDOM es simple de implentar pero si te queda alguna inquietud la puedes dejar en los comentarios, que con gusto te responderé.