¿Cómo puedo generar múltiples piezas de contenido en una plantilla de componente ember.js?
handlebars.js htmlbars (2)
El objetivo es definir una estructura de HTML que tenga más de un bloque de contenido declarado por la persona que llama. Por ejemplo, un encabezado, cuerpo y contenido. El marcado resultante debe ser:
<header>My header</header>
<div class="body">My body</div>
<footer>My footer</footer>
La plantilla que crea una instancia del componente definiría cada una de las tres secciones, My header
, My body
y My footer
.
Con Ruby on Rails, usaría content_for :header
para capturar el contenido del encabezado de la persona que llama, y el yield :header
para interpolarlo.
¿Es esto posible en ember.js?
A partir de noviembre v1.10, el rendimiento acepta parámetros. Sin embargo, los manillares todavía no permiten comparaciones en línea de valores variables. Al definir algunas propiedades en el componente, podemos acercarnos bastante a lo que hacen los rieles.
Según el ejemplo anterior, la plantilla del componente se vería así:
<header>{{yield header}}</header>
<div class="body">{{yield body}}</div>
<footer>{{yield footer}}</footer>
Y la definición del componente resolvería los argumentos variables para las declaraciones de rendimiento:
export default Ember.Component.extend({
header: {isHeader: true},
footer: {isFooter: true},
body: {isBody: true}
});
Esto significa que {{yield header}}
realidad está produciendo un objeto {isHeader: true}
para la plantilla consumidora. Entonces podemos usar una estructura anidada if / else para declarar las tres secciones como esta:
{{#my-comp as |section|}}
{{#if section.isHeader}}
My header
{{else if section.isBody}}
My body
{{else if section.isFooter}}
My footer
{{/if}}
{{/my-comp}}
La respuesta anterior puede estar desactualizada.
Hay un RFC aceptado para este problema; la API del bloque de plantillas con nombre permitirá pasar múltiples bloques a un componente.
A partir de Ember 2.3, los componentes contextuales permiten otro enfoque para este caso:
Divida su componente en múltiples subcomponentes y devuelva los subcomponentes al componente como parámetros de bloque; Esta configuración permite establecer el contenido de cada bloque de subcomponente.
Echa un vistazo a Twiddle - ejemplo completo .
// my-component.js
{{yield (hash
header = (component ''my-header'')
content = (component ''my-content'')
footer = (component ''my-footer'')
)}}
{{#unless hasBlock}}
{{my-header}}
{{my-content}}
{{my-footer}}
{{/unless}}
// my-{header/content/footer}.js
{{#if hasBlock}}
{{yield}}
{{else}}
Default xxxxx
{{/if}}
En este caso, podría usar el contenido del componente predeterminado o pasar el contenido específico a cualquier subcomponente como:
{{my-component}}
{{#my-component as |f|}}
{{f.header}}
{{#f.content}}
Custom content
{{/f.content}}
{{f.footer}}
{{/my-component}}
{{#my-component as |f|}}
{{#f.header}}
Custom header
{{/f.header}}
{{#f.content}}
Custom content
{{/f.content}}
{{#f.footer}}
Custom footer
{{/f.footer}}
{{/my-component}}
Esta solución no fuerza la estructura / API del componente, entonces el componente podría usarse incorrectamente si se omite un subcomponente, se agrega varias veces o tiene un orden incorrecto, en estos casos el componente generará un contenido no deseado.
Echa un vistazo a Twiddle - ejemplo completo .