[DOC] add a dedicated page on slots

closes #640
This commit is contained in:
Géry Debongnie
2020-02-15 10:08:49 +01:00
parent 1d7503913e
commit 69d35abe4f
5 changed files with 98 additions and 73 deletions
+1
View File
@@ -33,6 +33,7 @@ provided by Owl.
- [QWeb Engine](reference/qweb_engine.md) - [QWeb Engine](reference/qweb_engine.md)
- [Router](reference/router.md) - [Router](reference/router.md)
- [Store](reference/store.md) - [Store](reference/store.md)
- [Slots](reference/slots.md)
- [Tags](reference/tags.md) - [Tags](reference/tags.md)
- [Utils](reference/utils.md) - [Utils](reference/utils.md)
+2 -71
View File
@@ -15,7 +15,6 @@
- [Event Handling](#event-handling) - [Event Handling](#event-handling)
- [Form Input Bindings](#form-input-bindings) - [Form Input Bindings](#form-input-bindings)
- [References](#references) - [References](#references)
- [Slots](#slots)
- [Dynamic sub components](#dynamic-sub-components) - [Dynamic sub components](#dynamic-sub-components)
- [Error Handling](#error-handling) - [Error Handling](#error-handling)
- [Functional Components](#functional-components) - [Functional Components](#functional-components)
@@ -823,75 +822,6 @@ Note that these two examples uses the suffix `ref` to name the reference. This
is not mandatory, but it is a useful convention, so we do not forget to access is not mandatory, but it is a useful convention, so we do not forget to access
it with the `el` or `comp` suffix. it with the `el` or `comp` suffix.
### Slots
To make generic components, it is useful to be able for a parent component to _inject_
some sub template, but still be the owner. For example, a generic dialog component
will need to render some content, some footer, but with the parent as the
rendering context.
This is what _slots_ are for.
```xml
<div t-name="Dialog" class="modal">
<div class="modal-title"><t t-esc="props.title"/></div>
<div class="modal-content">
<t t-slot="content"/>
</div>
<div class="modal-footer">
<t t-slot="footer"/>
</div>
</div>
```
Slots are defined by the caller, with the `t-set` directive:
```xml
<div t-name="SomeComponent">
<div>some component</div>
<Dialog title="Some Dialog">
<t t-set="content">
<div>hey</div>
</t>
<t t-set="footer">
<button t-on-click="doSomething">ok</button>
</t>
</Dialog>
</div>
```
In this example, the component `Dialog` will render the slots `content` and `footer`
with its parent as rendering context. This means that clicking on the button
will execute the `doSomething` method on the parent, not on the dialog.
Default slot: the first element inside the component which is not a named slot will
be considered the `default` slot. For example:
```xml
<div t-name="Parent">
<Child>
<span>some content</span>
</Child>
</div>
<div t-name="Child">
<t t-slot="default"/>
</div>
```
Slots can define a default content, in case the parent did not define them:
```xml
<div t-name="Parent">
<Child/>
</div>
<span t-name="Child">
<t t-slot="default">default content</t>
</span>
<!-- will be rendered as: <div><span>default content</span></div> -->
```
### Dynamic sub components ### Dynamic sub components
It is not common, but sometimes we need a dynamic component name. In this case, It is not common, but sometimes we need a dynamic component name. In this case,
@@ -983,7 +913,8 @@ Using the `ErrorBoundary` is then extremely simple:
``` ```
Note that we need to be careful here: the fallback UI should not throw any Note that we need to be careful here: the fallback UI should not throw any
error, otherwise we risk going into an infinite loop. error, otherwise we risk going into an infinite loop (also, see the page on
[slots](slots.md) for more information on the `t-slot` directive).
Also, it may be useful to know that whenever an error is caught, it is then Also, it may be useful to know that whenever an error is caught, it is then
broadcasted to the application by an event on the `qweb` instance. It may be broadcasted to the application by an event on the `qweb` instance. It may be
+1 -1
View File
@@ -18,7 +18,7 @@ for modals (as in `bootstrap-modal`).
### Usage ### Usage
The content it will teleport is defined within the `<Portal>` node and The content it will teleport is defined within the `<Portal>` node and
internally uses the `default` [Slot](component.md#slots). internally uses the `default` [Slot](slots.md).
This slot must contain only **one** node, which in turn can have as many children as necessary. This slot must contain only **one** node, which in turn can have as many children as necessary.
+1 -1
View File
@@ -73,7 +73,7 @@ needs. Here is a list of all Owl specific directives:
| `t-key` | [Defining a key (to help virtual dom reconciliation)](#loops) | | `t-key` | [Defining a key (to help virtual dom reconciliation)](#loops) |
| `t-on-*` | [Event handling](component.md#event-handling) | | `t-on-*` | [Event handling](component.md#event-handling) |
| `t-transition` | [Defining an animation](animations.md#css-transitions) | | `t-transition` | [Defining an animation](animations.md#css-transitions) |
| `t-slot` | [Rendering a slot](component.md#slots) | | `t-slot` | [Rendering a slot](slots.md) |
| `t-model` | [Form input bindings](component.md#form-input-bindings) | | `t-model` | [Form input bindings](component.md#form-input-bindings) |
## Reference ## Reference
+93
View File
@@ -0,0 +1,93 @@
# 🦉 Slots 🦉
## Content
- [Overview](#overview)
- [Example](#example)
- [Reference](#reference)
## Overview
Owl is a template based component system. There is therefore a need to be able
to make generic components. For example, imagine a generic `Dialog`
component, which is able to display some arbitrary content.
Obviously, we want to use this component everywhere in our application, to
display various different content. The `Dialog` component is technically the
owner of its content, but is only a container. The user of the `Dialog` is
the component that want to _inject_ something inside the `Dialog`. This is
exactly what slots are for.
## Example
To make generic components, it is useful to be able for a parent component to _inject_
some sub template, but still be the owner. For example, a generic dialog component
will need to render some content, some footer, but with the parent as the
rendering context.
```xml
<div t-name="Dialog" class="modal">
<div class="modal-title"><t t-esc="props.title"/></div>
<div class="modal-content">
<t t-slot="content"/>
</div>
<div class="modal-footer">
<t t-slot="footer"/>
</div>
</div>
```
Slots are defined by the caller, with the `t-set` directive:
```xml
<div t-name="SomeComponent">
<div>some component</div>
<Dialog title="Some Dialog">
<t t-set="content">
<div>hey</div>
</t>
<t t-set="footer">
<button t-on-click="doSomething">ok</button>
</t>
</Dialog>
</div>
```
In this example, the component `Dialog` will render the slots `content` and `footer`
with its parent as rendering context. This means that clicking on the button
will execute the `doSomething` method on the parent, not on the dialog.
## Reference
Default slot: the first element inside the component which is not a named slot will
be considered the `default` slot. For example:
```xml
<div t-name="Parent">
<Child>
<span>some content</span>
</Child>
</div>
<div t-name="Child">
<t t-slot="default"/>
</div>
```
Default content: slots can define a default content, in case the parent did not define them:
```xml
<div t-name="Parent">
<Child/>
</div>
<span t-name="Child">
<t t-slot="default">default content</t>
</span>
<!-- will be rendered as: <div><span>default content</span></div> -->
```
Rendering context: the content of the slots is actually rendered with the
rendering context corresponding to where it was defined, not where it is
positioned. This allows the user to define event handlers that will be bound
to the correct component (usually, the grandparent of the slot content).