Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@samewave/ember-block-slots

Support for targeted yield slots within a component block

ember-addon, named yields, slots, ember, addon, component

readme

ember-block-slots

Travis Coveralls Ember Observer

Adds contextual layout to component interfaces.

Demo

Why does this matter?

"I know why this matters, take me straight to the usage"

Ember has a number of tools for component authors: a yield, block params, contextual components and block defaults (else/inverse). However, since only a single yield is available, Ember does not provide a way for component authors to hide complex layouts behind a component interface. For authors of higher-order components this is a problem.

Designing higher-order components (patterns of composite components)

Suppose you want to create a higher-order component that acts as an inventory browser.

Mock inventory browser

You want to arrange a title bar on the top of the page, a filter pane on the left and a list on the right. The title bar can be customized with summary information (text, badges, graphs) and contexual actions (e.g. keyword search, add). The filter pane needs to be wired to the list, but filtering should be handled in the route/controller. The list has a set of potential controls (e.g. sort, paginate, expand/collapse) and contextual actions based on the items selected that should also be handled in the route/controller.

There are two choices available

The first choice is to pre-select all the components (e.g. form, list, buttons, links, graphs) to fill these roles and proxy the relevant properties through the component interface, modifying the interface whenever additional features are available. Maybe your underlying components are stable and maybe your feature set never expands, but don't bet the house on it; it's more likely that you'll need to rev and release your component based on the progression of the components you select. This means a lot of maintenance and a broad interface - not ideal.

The second choice is to loosely couple the components, providing a number of CSS classes and rely on the consumer to wrap the components in the correct HTML to layout the pattern as required. This works fine for a single instance, but before you know it there are 10 instances of the pattern in your product and as the design team keeps making minor (or major) tweaks and each of your browsers is starting to look a bit different...

Alright, I lied, there is a third choice

You use this addon :wink:

With multiple yield targets available, you're now able to combine the structured DOM from the first choice with the loose coupling of the second choice. Now consumers of the addon don't need to worry about:

  • Layout changes "Oh look, the design team made the title bar a footer..."
  • Component updates "Lists now support pagination!...but this component hasn't upgraded..."
  • Proxying actions "But I really need 10 contextual action buttons/links in this case..."

Seems promising, how does this work?

Installation

ember install ember-block-slots

Usage

Import and apply the SlotsMixin in the component where you want to provide multiple yield slots.

import Ember from 'ember'
import SlotsMixin from 'ember-block-slots'

export default Ember.Component.extend(SlotsMixin, {

In the component template, yield once to allow instances to register block slots, then provide one or more named yield slots

{{yield}}

{{#yield-slot 'name'}}
  <div class='surrounding-layout'>
    {{yield}}
  </div>
{{/yield-slot}}

When using the component, target content for the yield slots using block slots

{{#pattern-component}}
  {{#block-slot 'name'}}
    <div>Content for the yield</div>
  {{/block-slot}}
{{/pattern-component}}

Of course, this is only a glimpse at the interface designs now available to you. Block slots also support:

See the demo for additional syntax and examples.

Issues/requests

Found a corner case? Thought of a design pattern we haven't listed? PRs and issues are welcome!

Contributing

This project uses pr-bumper https://github.com/ciena-blueplanet/pr-bumper to publish to npm - add a semver comment in your PR in the following format: #fix# / #minor# / #major#

We also lint the project using eslint - to check for errors and fix basic style issues run ./node_modules/.bin/eslint . --fix in the root of the project (probably a better command for this)

Credits

Thanks to @runspired for the initial inspiration for this implementation.

changelog

1.1.11 (2017-08-01)

1.1.10 (2017-04-26)

Delay the initialization of the block-slot to the didInsertElement callback.

Assertion Failed: You modified "isActive" twice on <xxx@component:yield-slot::ember1525> in a single render. It was rendered in "component:yield-slot" and modified in "component:block-slot". This was unreliable and slow in Ember 1.x and is no longer supported. See https://github.com/emberjs/ember.js/issues/13948 for more details.


This change is Reviewable

1.1.9

Expand ember-prop-types dependency range and remove unnecessary installation blueprint.


This change is Reviewable

1.1.8

  • Added a PULL_REQUEST_TEMPLATE.md file

This change is Reviewable

1.1.7

  • 2.10.0 now freezes params, need to clone Array before Ember.Aing

This change is Reviewable

1.1.6

  • Forgot one instance where contains was used. Converting that to includes fixes the deprecations in 2.8.

This change is Reviewable

1.1.5

  • Use includes method over contains to fix deprecation in Ember 2.8

This change is Reviewable

1.1.4

  • Removed the 'complex' scenario from the demo, this should be written in a clearer way

This change is Reviewable

1.1.3

  • Yield slots will now find the nearest component with slots to register against - a direct parent with slots is no longer required

1.1.2

  • Added ember-prop-types to the addon blueprint to install the dependency during ember install

1.1.1

  • Added ember-prop-types to the addon blueprint to install the dependency during ember install

1.1.0

Supporting nested block slots

1.0.1

  • ensures that the array is unique per instance

fixes #31

1.0.0

  • Overhauled the project to provide a cleaner/simpler interface and unlock additional features
  • Updated the README and demo to provide a clearer use case for the addon and more usage examples
  • Refer to the demo for the full feature set and syntax

BREAKING CHANGES

  • A mixin is now required to enable slots for a component: import SlotsMixin from 'ember-block-slots
  • block-params are now specified against yield-slot instead of yield
  • as |slot| is no longer required on the component interface
  • slot is no longer required on the block-slot interface

0.12.4

Non-Breaking

  • Fixed added arguments to super() calls in block-slot.js and yield-slot.js

0.12.3

No CHANGELOG section found in Pull Request description. Use a # CHANGELOG section in your Pull Request description to auto-populate the CHANGELOG.md

0.12.2

  • Updated Array.from usage and instead we define each computed property for yieldedSlot.params.
  • Removed Unit test for block-slot component since we do not need to verify the number of yieldedSlot.params being generated dynamically.
  • Removed Entry in travis.yml to run on the latest version of Firefox.