mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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).
|
||||||
Reference in New Issue
Block a user