javascript - opts - Pasar variables a través de manillares parciales
handlebars raw (7)
Esto es muy posible si escribe su propio ayudante. Estamos utilizando un $
helper personalizado para lograr este tipo de interacción (y más):
/*///////////////////////
Adds support for passing arguments to partials. Arguments are merged with
the context for rendering only (non destructive). Use `:token` syntax to
replace parts of the template path. Tokens are replace in order.
USAGE: {{$ ''path.to.partial'' context=newContext foo=''bar'' }}
USAGE: {{$ ''path.:1.:2'' replaceOne replaceTwo foo=''bar'' }}
///////////////////////////////*/
Handlebars.registerHelper(''$'', function(partial) {
var values, opts, done, value, context;
if (!partial) {
console.error(''No partial name given.'');
}
values = Array.prototype.slice.call(arguments, 1);
opts = values.pop();
while (!done) {
value = values.pop();
if (value) {
partial = partial.replace(/:[^/.]+/, value);
}
else {
done = true;
}
}
partial = Handlebars.partials[partial];
if (!partial) {
return '''';
}
context = _.extend({}, opts.context||this, _.omit(opts, ''context'', ''fn'', ''inverse''));
return new Handlebars.SafeString( partial(context) );
});
Actualmente me ocupo de handlebars.js en una aplicación express.js. Para mantener las cosas modulares, dividí todas mis plantillas en parciales.
Mi problema : no pude encontrar una forma de pasar variables a través de una invocación parcial. Digamos que tengo un parcial que se ve así:
<div id=myPartial>
<h1>Headline<h1>
<p>Lorem ipsum</p>
</div>
Supongamos que registré este parcial con el nombre ''myPartial''. En otra plantilla, puedo decir algo como:
<section>
{{> myPartial}}
</section>
Esto funciona bien, el parcial se representará como se espera y soy un desarrollador feliz. Pero lo que ahora necesito es una forma de pasar diferentes variables a través de esta invocación, para verificar dentro de un parcial, por ejemplo, si se da un título o no. Algo como:
<div id=myPartial>
{{#if headline}}
<h1>{{headline}}</h1>
{{/if}}
<p>Lorem Ipsum</p>
</div>
Y la invocación debería verse más o menos así:
<section>
{{> myPartial|''headline'':''Headline''}}
</section>
más o menos.
Sé que puedo definir todos los datos que necesito antes de representar una plantilla. Pero necesito una forma de hacerlo, como acabo de explicar. ¿Hay alguna manera posible?
Esto también se puede hacer en versiones posteriores de manillares utilizando la notación key=value
:
{{> mypartial foo=''bar'' }}
Permitiéndole pasar valores específicos a su contexto parcial.
Referencia: contexto diferente para el parcial # 182
La respuesta aceptada funciona muy bien si solo quiere usar un contexto diferente en su parcial. Sin embargo, no le permite hacer referencia al contexto principal. Para pasar múltiples argumentos, necesita escribir su propio ayudante. Aquí hay un ayudante de trabajo para Handlebars 2.0.0
(la otra respuesta funciona para las versiones <2.0.0
):
Handlebars.registerHelper(''renderPartial'', function(partialName, options) {
if (!partialName) {
console.error(''No partial name given.'');
return '''';
}
var partial = Handlebars.partials[partialName];
if (!partial) {
console.error(''Couldnt find the compiled partial: '' + partialName);
return '''';
}
return new Handlebars.SafeString( partial(options.hash) );
});
Luego, en su plantilla, puede hacer algo como:
{{renderPartial ''myPartialName'' foo=this bar=../bar}}
Y en su parcialidad, podrá acceder a esos valores en un contexto como:
<div id={{bar.id}}>{{foo}}</div>
Los parciales de manillar toman un segundo parámetro que se convierte en el contexto para el parcial:
{{> person this}}
En las versiones v2.0.0 alpha y posteriores, también puede pasar un hash de parámetros con nombre:
{{> person headline=''Headline''}}
Puede ver las pruebas para estos escenarios: https://github.com/wycats/handlebars.js/blob/ce74c36118ffed1779889d97e6a2a1028ae61510/spec/qunit_spec.js#L456-L462 https://github.com/wycats/handlebars.js/blob/e290ec24f131f89ddf2c6aeb707a4884d41c3c6d/spec/partials.js#L26-L32
Parece que quieres hacer algo como esto:
{{> person {another: ''attribute''} }}
Yehuda ya te dio una manera de hacer eso:
{{> person this}}
Pero para aclarar:
Para dar a su parcial sus propios datos, simplemente déle su propio modelo dentro del modelo existente, así:
{{> person this.childContext}}
En otras palabras, si este es el modelo que le está dando a su plantilla:
var model = {
some : ''attribute''
}
A continuación, agregue un nuevo objeto para dar al parcial:
var model = {
some : ''attribute'',
childContext : {
''another'' : ''attribute'' // this goes to the child partial
}
}
childContext
convierte en el contexto de lo parcial, como dijo Yehuda: en eso, solo ve el campo como another
, pero no ve (o le importa un poco el campo). Si tenía una id
en el modelo de nivel superior y repite la id
nuevamente en el childContext, eso funcionará bien ya que el parcial solo ve lo que hay dentro de childContext
.
Por las dudas, esto es lo que hice para obtener argumentos parciales, más o menos. Creé un pequeño ayudante que toma un nombre parcial y un hash de parámetros que se pasarán al parcial:
Handlebars.registerHelper(''render'', function(partialId, options) {
var selector = ''script[type="text/x-handlebars-template"]#'' + partialId,
source = $(selector).html(),
html = Handlebars.compile(source)(options.hash);
return new Handlebars.SafeString(html);
});
La clave aquí es que los ayudantes de Handlebars aceptan un hash de argumentos tipo Ruby . En el código auxiliar, se incluyen como parte de las últimas options
argumento de la función en su miembro hash
. De esta forma, puede recibir el primer argumento, el nombre parcial, y obtener los datos después de eso.
Entonces, es probable que desee devolver Handlebars.SafeString
del helper o usar "triple-stash" - {{{
- para evitar que doble escape.
Aquí hay un escenario de uso más o menos completo:
<script id="text-field" type="text/x-handlebars-template">
<label for="{{id}}">{{label}}</label>
<input type="text" id="{{id}}"/>
</script>
<script id="checkbox-field" type="text/x-handlebars-template">
<label for="{{id}}">{{label}}</label>
<input type="checkbox" id="{{id}}"/>
</script>
<script id="form-template" type="text/x-handlebars-template">
<form>
<h1>{{title}}</h1>
{{ render ''text-field'' label="First name" id="author-first-name" }}
{{ render ''text-field'' label="Last name" id="author-last-name" }}
{{ render ''text-field'' label="Email" id="author-email" }}
{{ render ''checkbox-field'' label="Private?" id="private-question" }}
</form>
</script>
Espero que esto ayude a alguien. :)
Sí, llegué tarde, pero puedo agregar para los usuarios de Ensamblar : puede usar el "parseJSON"
http://assemble.io/helpers/helpers-data.html . (Descubierto en https://github.com/assemble/assemble/issues/416 ).