como {{ helper1 helper2 text }}
, você sabe que às vezes apenas um ajudante não é suficiente para fazer o trabalho.
Eu acho que deveria haver uma maneira de aninhar expressões, como esta: {{headerText {{getTitle "my_page"}}}}
.
Isso não é compatível no momento e não tenho planos de oferecer suporte.
No entanto, você poderia teoricamente criar um ajudante que consome intencionalmente e acorrenta outros ajudantes:
{{chain "helper1" "helper2" text}}
Se alguém estiver interessado, criei um ajudante:
Handlebars.registerHelper('chain', function () {
var helpers = [], value;
$.each(arguments, function (i, arg) {
if (Handlebars.helpers[arg]) {
helpers.push(Handlebars.helpers[arg]);
} else {
value = arg;
$.each(helpers, function (j, helper) {
value = helper(value, arguments[i + 1]);
});
return false;
}
});
return value;
});
Funciona assim:
{{chain "taxAdd" "formatPrice" this.product.price}}
@Znarkus que introduz uma dependência para jQuery
@jrajan Eu só usei jQuery.each
, sinta-se à vontade para reescrever com quaisquer que sejam suas preferências.
Se alguém estiver interessado em uma versão agnóstica do jQuery:
Handlebars.registerHelper('chain', function() {
var helpers = [];
var args = Array.prototype.slice.call(arguments);
var argsLength = args.length;
var index;
var arg;
for (index = 0, arg = args[index];
index < argsLength;
arg = args[++index]) {
if (Handlebars.helpers[arg]) {
helpers.push(Handlebars.helpers[arg]);
} else {
args = args.slice(index);
break;
}
}
while (helpers.length) {
args = [helpers.pop().apply(Handlebars.helpers, args)];
}
return args.shift();
});
Um problema com ambas as implementações é digno de nota: se algum dos argumentos tiver a intenção de serem valores a serem passados para um auxiliar, mas também forem (coercíveis para) strings que correspondem ao nome de um auxiliar existente, haverá resultados inesperados.
Aqui estão duas implementações. Ambos permitem que você tenha vários argumentos enviados para cada auxiliar, ao contrário dos exemplos anteriores.
Eles também são escritos em script de café e dependem de sublinhado ou lodash.
O primeiro permite que você faça algo assim:
{{{chain 'join-strings' 'link-twitter-handles' '@' twitterUsername}}}
Mas algo assim produziria resultados inesperados:
{{{chain 'join-strings' 'link-twitter-handles' '@' 'join-strings' twitterUsername}}}
Handlebars.registerHelper 'chain', ->
# Get rid of the options hash
args = Array.prototype.slice.call arguments, 0, -1
helpers = []
argsForHelpers = null
value = undefined
_.each args, (arg, i) ->
if Handlebars.helpers[arg]
helpers.push Handlebars.helpers[arg]
else if not value # Only call the helpers once
value = arg
unless argsForHelpers
argsForHelpers = args[i+1..-1]
argsForHelpers.unshift value
_.each helpers, (helper) ->
argsForHelpers[0] = value
value = helper.apply null, argsForHelpers
value
Este segundo exemplo tem um separador que permite chain
separar os auxiliares dos argumentos.
O auxiliar irá assumir que cada argumento antes do separador é um auxiliar e todos os outros devem ser passados como argumentos para os auxiliares.
Handlebars.registerHelper 'chain', ->
# Get rid of the options hash
args = Array.prototype.slice.call arguments, 0, -1
helpers = []
for arg,i in args
if arg is '--'
argsForHelpers = args.slice i + 1
value = argsForHelpers[0]
break
else
helpers.push Handlebars.helpers[arg]
_.each helpers, (helper) ->
argsForHelpers[0] = value
value = helper.apply null, argsForHelpers
value
Dado este modelo:
{{{chain 'join-strings' 'link-twitter-handles' '@' 'join-strings' twitterUsername}}}
e este objeto:
{twitterUsername: 'abc'}
Poderíamos esperar um modelo compilado como este:
<a href="https://twitter.com/join-stringsabc">@join-stringsabc</a>
Peguei a implementação de
/**
* Takes an arbitrary number of arguments, the first of which is the operation type 'AND' or 'OR'.
* Following that will be a list of block helper names prefixed by '!!'.
* Calls each block helper with the remaining arguments.
*
* <strong i="7">@returns</strong> {string} returns options.fn(this) or options.inverse(this) depending on result of each helper and operation type
*/
Handlebars.registerHelper('chainBlockHelpers', function() {
var index, arg, helperResult, pass,
helpers = [],
args = Array.prototype.slice.call(arguments),
argsLength = args.length,
options = args[argsLength-1],
operation = args.shift(),
passVal = options.fn(this),
failVal = options.inverse(this);
if (operation !== 'AND' && operation !== 'OR')
throw new Error ('chainBlockHelpers only supports "AND" or "OR" operations.')
for (index = 0, arg = args[index]; index < argsLength; arg = args[++index]) {
if (typeof arg == 'string' && arg.startsWith('!!') && Handlebars.helpers[arg.substr(2)]) {
helpers.push(Handlebars.helpers[arg.substr(2)]);
} else {
args = args.slice(index);
break;
}
}
if (operation === 'AND') {
pass = true;
while (helpers.length) {
helperResult = helpers.pop().apply(Handlebars.helpers, args);
if (helperResult == failVal) {
pass = false;
break;
}
}
} else {
pass = false;
while (helpers.length) {
helperResult = helpers.pop().apply(Handlebars.helpers, args);
if (helperResult == passVal) {
pass = true;
break;
}
}
}
return pass ? passVal : failVal;
});
isso parece ter suporte nativo usando algo como:
{{ helper1 (helper2 text) }}
Em alguns casos, você pode fazer seus ajudantes trabalharem como:
{{#helper1}}{{helper2}}content{{/helper2}}{{/helper1}}
@Znarkus Usando seu método, quando passo em dois auxiliares que têm strings seguras aplicadas, minhas quebras de código. Na primeira vez que passo os dados, ele vem como uma string, mas no segundo filtro, o valor que está sendo passado parece ser um objeto? No meu depurador, ele é mostrado como 'uma quebra de linha e, em seguida, string:' meu valor '; Não tenho certeza do que SafeString faz com o valor, mas passar por ele duas vezes não parece funcionar muito bem.
Handlebars.registerHelper('shortNumber', function (value) {
//return new Handlebars.SafeString(iSpot.number.shortNumber(value)); // Breaks
return iSpot.number.shortNumber(value); // Works
});
Handlebars.registerHelper('asDollars', function (value) {
//return new Handlebars.SafeString(iSpot.number.asDollars(value)); // Breaks
return iSpot.number.asDollars(value); // Works
});
Abordagem +1 {{pluralize (titleize (humanize schema.name))}}
+1 que parece uma sintaxe limpa e agradável.
+1 @amwmedia Funciona perfeitamente, obrigado
A abordagem @amwmedia funciona como um charme, mas apenas sem Handlebars.SafeString()
como @cssagogo mencionado acima.
Então você pode fazer smth. Como:
{{> partial text=(concat value (default extension 'PDF')) }}
obrigado
Eu corri para esse problema sozinho. Sei que estou muito atrasado nisso, mas tenho uma solução que funcionou para mim. Por favor, me perdoe se isso já foi mencionado (não tive tempo para verificar). Esta não é a solução mais legal e, tecnicamente, não é uma resposta direta à sua pergunta, mas é uma solução para o problema (executando várias funções em um valor).
Eu mantenho todas as minhas funções auxiliares em um arquivo separado. Como estão todos no mesmo lugar, posso passar o valor para um auxiliar e, em seguida, apenas chamar todas as outras funções que tenho no arquivo da função auxiliar. Assim:
{{ function1 value }}
arquivo auxiliar
function2 (value) {
// code
}
function1 (value) {
// code
function2(value)
// code
return value;
}
Obviamente, esta é uma maneira simples de poder usar quantas funções desejar. Você pode até designar uma função de base que atua como seu "encadeador".
{{ chainer value }}
arquivo auxiliar
function1 (value) {
// code
}
function2 (value) {
// code
}
function3 (value) {
// code
}
function4 (value) {
// code
}
function chainer(value) {
function1(value)
function2(value)
function3(value)
function4(value)
return value;
}
Eu mesmo não fiz isso, mas não vejo por que não funcionaria.
Nota Você só precisa registrar as funções que deseja usar em seu html como ajudantes do guiador. Eu pessoalmente tenho todos os meus registrados porque os utilizo independentemente uns dos outros, mas você não precisa se não se prevê a necessidade de usá-los diretamente.
Um retrocesso à programação procedural :)
Comentários muito úteis
isso parece ter suporte nativo usando algo como:
{{ helper1 (helper2 text) }}