A component that "forwards" passed blocks to a child component. For example, imagine we have a component called MiniCard
that accepts a named block called header
. It is invoked like this:
The implementation of MiniCard
uses the has-block
helper to emit additional header-related DOM elements only in the case that the header
block is provided:
Next, we want to implement a component called JobCard
that uses MiniCard
. JobCard
also takes an optional named block called header
, but wants to pass it along to MiniCard
rather than yield the block itself.
Named blocks are (intentionally for the MVP) not exposed as first-class values. In order for a component to "pass" a named block to a child component, it must create a new named block and yield the passed block within the new block. For example, JobCard
defines a new header
named block when invoking MiniCard
, and yields its own header
block inside:
This solution works so long as the header
block is always provided. However, in this case, the header
block was intended to be optional, because different DOM output is emitted by MiniCard
if the header
block is not present. In this case, the MiniCard
will always render the additional <div class="mini-card-header">
element, even if it is unwanted because no header
block was passed to the parent JobCard
.
One workaround is to check for the existence of the named block in a conditional in the parent component template, invoking the child component with the named block if the passed block exists and without the named block if it doesn't. For example:
While this solves the problem, it requires tedious, verbose boilerplate code to accomplish. It also makes bugs more likely, as both component invocations (with and without the block) must be updated if the arguments passed to the component change.
Worse, using this approach when there are multiple optional blocks creates a combinatorial explosion of boilerplate. Each permutation of possible block configurations would need to be handled in the template, quickly leading to a verbose, confusing, hard-to-maintain template.
Syntactic support for passing an existing in-scope named block as a named block to a child component.
Importantly, named blocks provided via the from
syntax preserve "undefinedness." For example, if no named block was provided to the parent component that matches the name specified in from="blockName"
, {{has-block "blockName"}}
would evaluate to false
in the child component.
For example:
Invoking Parent
like this:
Produces the following output: