Title
Content here.
The following feels like it does not belong in the README. Maybe a Medium post would be better? Or in a separate .md file? Stashing it here for now.
## Composing Components
Components can use other components in their update functions. Some useful patterns for component composition are:
* [Nesting](#nesting)
* [Containment](#containment)
* [Conditional Rendering](#conditional_rendering)
### Nesting
Nesting is useful when instances of one component will contain instances of other components. Nesting can be achieved by invoking child components within the update function of the parent component, possibly deriving the value of children `props` from the `props` passed into the parent component.
Here's an example of a `post` component that composes two other components, `heading` and `paragraph`.
```js
var heading = d3.component("h1")
.update(function (selection, props){
selection.text(props.text);
}),
paragraph = d3.component("p")
.update(function (selection, props){
selection.text(props.text);
}),
post = d3.component("div", "post")
.update(function (selection, props){
selection
.call(heading, { text: props.title })
.call(paragraph, { text: props.content });
});
```
Here's how we would render an instance of the `post` component.
```js
d3.select("#some-container-div");
.call(post, {
title: "Title",
content: "Content here."
});
```
The following DOM structure will be rendered.
```html
Content here.
Here's an example of rendering multiple component instances.
```js
d3.select("#some-container-div")
.call(post, [
{ title: "A Title", content: "a content" },
{ title: "B Title", content: "b content" },
]);
```
The following HTML structure will be rendered.
```html
a content
b content
For a full working example using the components above, see [Posts with d3-component](http://bl.ocks.org/curran/fc8f6989901628e2e79d6374849453ed).
### Containment
Sometimes children components are not known in advance. This is often the case for components that serve as "boxes" that can contain arbitrary content, such as cards or dialogs. There are no special constructs provided for achieving this, but it can be achieved by using a pattern in which the child component and its props are both passed in via the props of the parent component.
Here's an example of a `card` component that can render arbitrary children.
```js
var card = d3.component("div", "card")
.enter(function (selection){
selection
.append("div").attr("class", "card-block")
.append("div").attr("class", "card-text");
})
.update(function (selection, props){
selection.select(".card-text")
.call(props.childComponent, props.childProps);
});
```
Here's how we can use this `card` component to render a card that contains instances of the `post` component.
```js
d3.select("#some-container-div")
.call(card, {
childComponent: post,
childProps: [
{ title: "A Title", content: "a content" },
{ title: "B Title", content: "b content" },
]
});
```
The following DOM structure will be rendered.
```html
a content
b content
### Conditional Rendering
Sometimes components should render sub-components only under certain conditions. To achieve this, the `props` passed into the sub-component can either be `[]` to render zero component instances, or any other value to render one or many component instances. Even if a sub-component is not rendered, it still needs to be invoked with its `props` as `[]`, in the case that it was rendered previously and its instances need to be removed from the DOM.
Here's an example of a `fruit` component that conditionally renders either `apple` or `orange` components.
```js
var apple = d3.component("span", "apple")
orange = d3.component("span", "orange")
fruit = d3.component("div", "fruit")
.update(function (selection, props){
selection
.call(apple, props.type === "apple"? {} : [])
.call(orange, props.type === "orange"? {} : [])
});
```
Here's how we can use this `fruit` component.
```js
d3.select("#some-container-div")
.call(fruit, [
{ type: "apple" },
{ type: "orange" },
{ type: "apple" },
{ type: "apple" },
{ type: "orange" }
]);
```
The following DOM structure will be rendered.
```html
This issue has not been assessed yet.
A short digest of beginner-friendly GitHub issues.