question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Is component/partial composition possible?

See original GitHub issue

I’ve read through quite a few of the open issues and PRs about “blocks” etc, but I’m unclear whether they solve my particular problem, or whether my problem is already achievable so please forgive me for logging this “issue” if it is.

I’m using Eleventy, a static site generator to build a website. It supports a lot of templating languages, but EJS] has been my favourite to work with in that it’s “just JavaScript”, except, I cannot figure out how to do component composition, or whether it’s at all possible. The EJS docs are… lacking.

What I want to achieve is similar to what you’d do in React or Vue with props.children or <slot>, where you compose components, but it would obviously be done with partials here.

For example, say I had a grid-item partial that accepted sizes it could render at, its tag name and “children”, something like:

<%- include('../grid-item', {
  size: '50',
  tag: 'li',
  children: ANOTHER-INCLUDE,
}); %>

However, even the above example is a bit limiting, so what I’d really like to achieve is something like:

<%- include('../grid', {
  tag: 'ul',
}, () => { %>
  <%- include('../grid-item', {
    size: '50',
    tag: 'li',
  }, () => { %>
    <div>ANY MARKUP</div>
  <% }); %>
<% }); %>

Is this possible? Am I approaching this from the wrong angle?

Eleventy supports a workaround for this with Paired Shortcodes for Nunjucks and Liquid, but both of those templating languages seem severely limited. Handlebars supports this via its @partial-block syntax, but wrangling Handlebars to even remotely do what’s possible in EJS is excruciating.

Any help would be greatly appreciated.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
stowballcommented, Jun 2, 2019

Another good use case example is a container component, which can be re-used within a header, main content modules and the footer to create a centered, max-width element within a full-bleed container, which in Vue would be created like this:

<script>
export default {
  styles: `
    margin-horizontal:auto
    max-width:container
    padding-horizontal:24
    @mq-768--padding-horizontal:32
  `,
  props: {
    as: {
      default: 'div',
      type: String,
    },
  },
};
</script>

<template>
  <component
    v-bind:class="styles"
    v-bind:is="as"
  >
    <slot></slot>
  </component>
</template>

and would be used in multiple components like so:

<template>
  <header>
    <container>
      logo, nav etc
    </container>
  </header>
  
  <container as="main">
    body content
  </container>
  
  <footer>
    <container>
      social icons etc
    </container>
  </footer>
</template>

Thinking how Vue and React handle it, perhaps a closing tag syntax isn’t that bad 😊

0reactions
DaveOrDeadcommented, Oct 15, 2019

It seems to me that using closing tag syntax could be a good way to go. You could also do it via a parameter passed to the same component file so that your opening and closing tags for a component remain together.

E.g

<%- include('grid/grid', {className: 'foo'}); %>
    
    <%- include('grid/cell', {className: 'bar'}); %>
        
        <p>Some child content</p>

    <%- include('grid/cell', {door: 'close'}); %>

<%- include('grid/grid', {door: 'close'); %>

door is just an example, I’m sure something more semantic could be thought of - I was just thinking of something that opens and closes. (Even self-close I guess)

Then in the component file grid/cell.ejs you can have:

<% if (locals.door !== 'close') { %>
    
    <div class="l-grid__item <%= className %>">

<% } %>

// Children render here

<% if (locals.door === 'close') { %>
    
    </div>

<% } %>

Personally I think it’s nice being able to see all the code for a component in the same place without needing to have a separate start and end file

Read more comments on GitHub >

github_iconTop Results From Across the Web

Application of an improved thermodynamic description of ...
Application of an improved thermodynamic description of multilayer surface compositions of binary alloys · Abstract · References · Author information · Rights and ......
Read more >
Composition-dependent thermodynamic and mass-transport ...
When the composition dependence of the transference number is already known — as is the case here — a rescaled concentration-cell potential ......
Read more >
Estimation of Botanical Composition in Mixed Clover–Grass ...
This study aims to provide an effective image analysis method for clover detection and botanical composition (BC) estimation in clover–grass ...
Read more >
Partial pressure - Wikipedia
In a mixture of gases, each constituent gas has a partial pressure which is the notional ... Content is available under CC BY-SA...
Read more >
Distillation Fundamentals - Neutrium
... or more streams which have compositions different to the feed stream. ... compositions at equilibrium due to component partial pressure.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found