ractivejs/ractive — pull request #1141 by Rich-Harris (2014-08-24 01:51:03+00:00)
Title: first stab at {{yield}}

This pull request scratches an itch I've had for some time. I'm not sure if I've got it completely right yet, so I won't merge this immediately - would be good to get some feedback first, so if you have any then don't be shy.

## The what

The basic idea is that inside component templates, you can use a `{{yield}}` declaration to insert the contents of the component as specified in the parent template. So you might have something like

```html

In here, we can insert arbitrary HTML.

We can use {{mustaches}} without passing data via the component.

Events are fired in the context of the parent, NOT the flippable-card component.

log instance to console

{{title}}

{{yield}}

```

## The why

This looks similar to the existing 'special' `{{>content}}` partial, but it's not - `{{>content}}` renders everything in the context of the child, not the parent. That's inconvenient and unexpected - I often get confused as to why my events don't seem to be firing, until I remember that I need to do nonsense like this:

```html

click me

```

Ugh. Event bubbling across component boundaries is [in the works](https://github.com/ractivejs/ractive/pull/1117) and is going to make life much easier, but in this case I believe the event *shouldn't have to cross a boundary*, and should be fired in the context of the parent instance. The same goes, in reverse, for data - in order to render `{{foo}}` correctly, there's no real reason that the `widget` component should know anything about the value of `foo`.

## The how

Surprisingly simple (to my relief) - there's a new `Yielder` item which is created when `{{yield}}` is encountered. It attaches itself to the DOM managed by the component, and the component controls its lifecycle, but as far as the virtual DOM that replaces `{{yield}}` is concerned, it belongs to the parent, not the component.

-------

I've been putting off implementing this for far too long on the grounds that `{{>content}}` is enough, but it's really not. Issue #1028 was the straw that broke the camel's back. I don't think I've ever encountered a situation where it actually makes sense to use `{{>content}}` instead of `{{yield}}`, so unless other people have examples (@martypdx I seem to recall you did - is that still the case?) I'd be in favour of gradually deprecating it.

## Next steps

* Determine whether `{{yield}}` is the right token to use. (It's how Ember do things. Polymer use `` - I'm not sure if that's a web components/shadow DOM thing or a Polymer thing, and if the first whether it's a standard that is likely to change. Angular use `ng-transclude`.) I think it's a good choice - element notation doesn't seem appropriate, and `yield` is a reserved word in JavaScript so it's not suitable for data-binding anyway
* Once we're happy, merge this PR and start using it, to see if there are things we haven't thought of yet
* Have a think about how parent and child components can become aware of each other and co-operate (in the way that `` and `
` elements work together to make a dropdown, or the `` and `` example on Angular's homepage) - particularly in situations where one or more of them implement custom render methods (e.g. components that render to canvas, or do audio stuff, or whatever).

Thanks for reading this far!