foreman/developer_docs/slot-and-fill.asciidoc @ develop
5e7343ec | MariaAga | [[slot-and-fill]]
|
|
27417efd | Amir Fefer | # Slot And Fill
|
|
5e7343ec | MariaAga | :toc: right
|
|
:toclevels: 5
|
|||
27417efd | Amir Fefer | ||
5e7343ec | MariaAga | Slot & Fill allows plugins to extend foreman core functionality in the UI.
|
|
34ca76de | Amir Fefer | ||
## Current Slots List
|
|||
e7c0ad82 | Avi Sharvit | ||
5e7343ec | MariaAga | You can find current slots by search which React component use the `<Slot>` component.
|
|
You can find .erb pages that use `<Slot>` component by searching for `slot` helper.
|
|||
7e9415db | Ondrej Prazak | ||
27417efd | Amir Fefer | ||
## Components
|
|||
### Slot
|
|||
e7c0ad82 | Avi Sharvit | ||
27417efd | Amir Fefer | `<Slot>` is an opinionated extension point which responsible of rendering its fills
|
|
a Slot can support multiple fills, rendering by weight order by the `multi` prop
|
|||
if there is no such prop, it will render the max weighted fill.
|
|||
### Fill
|
|||
e7c0ad82 | Avi Sharvit | ||
27417efd | Amir Fefer | a fill is the filled object of a slot
|
|
#### Component fill
|
|||
e7c0ad82 | Avi Sharvit | a fill that contains a child component, which rendered by a dedicated slot
|
|
_core_
|
|||
27417efd | Amir Fefer | ```js
|
|
41a3edb3 | Jeremy Lenz | <Slot id="slot-id">
|
|
a default child // can be empty
|
|||
</Slot>
|
|||
27417efd | Amir Fefer | ```
|
|
e7c0ad82 | Avi Sharvit | _plugin A_
|
|
27417efd | Amir Fefer | ```js
|
|
e7c0ad82 | Avi Sharvit | <Fill slotId="slot-id" id="some-id" weight={100}>
|
|
<div> some text </div>
|
|||
5e7343ec | MariaAga | </Fill>
|
|
27417efd | Amir Fefer | ```
|
|
e7c0ad82 | Avi Sharvit | _plugin B_
|
|
27417efd | Amir Fefer | ```js
|
|
e7c0ad82 | Avi Sharvit | <Fill slotId="slot-id" id="some-id" weight={200}>
|
|
<div> some text </div>
|
|||
5e7343ec | MariaAga | </Fill>
|
|
27417efd | Amir Fefer | ```
|
|
Plugin B has a fill with a higher weight, therefore it will be rendered in a dedicated slot.
|
|||
#### Component fill - remdering multiple fills
|
|||
e7c0ad82 | Avi Sharvit | ||
27417efd | Amir Fefer | If a slot has a `multi` prop, and it has multiple fills, it will render these fills by weight order
|
|
e7c0ad82 | Avi Sharvit | _core_
|
|
27417efd | Amir Fefer | ```js
|
|
e7c0ad82 | Avi Sharvit | <Slot multi id="slot-id" />
|
|
27417efd | Amir Fefer | ```
|
|
e7c0ad82 | Avi Sharvit | _plugin A_
|
|
27417efd | Amir Fefer | ```js
|
|
e7c0ad82 | Avi Sharvit | <Fill slotId="slot-id" id="some-id" weight={100}>
|
|
<div> some text </div>
|
|||
5e7343ec | MariaAga | </Fill>
|
|
27417efd | Amir Fefer | ```
|
|
e7c0ad82 | Avi Sharvit | _plugin B_
|
|
27417efd | Amir Fefer | ```js
|
|
e7c0ad82 | Avi Sharvit | <Fill slotId="slot-id" id="some-id" weight={200}>
|
|
<div> some text </div>
|
|||
5e7343ec | MariaAga | </Fill>
|
|
27417efd | Amir Fefer | ```
|
|
Plugin B's fill will be render first
|
|||
#### Props fill
|
|||
e7c0ad82 | Avi Sharvit | ||
27417efd | Amir Fefer | a fill that contains an `overrideProps` object
|
|
those props are given to the slot's children
|
|||
e7c0ad82 | Avi Sharvit | _core_
|
|
27417efd | Amir Fefer | ||
```js
|
|||
e7c0ad82 | Avi Sharvit | const TextWrapper = ({ text }) => <div>{text}</div>;
|
|
27417efd | Amir Fefer | ||
e7c0ad82 | Avi Sharvit | <Slot id="slot-id">
|
|
<TextWrapper text="some default text" />
|
|||
5e7343ec | MariaAga | </Slot>;
|
|
27417efd | Amir Fefer | ```
|
|
e7c0ad82 | Avi Sharvit | _plugin A_
|
|
27417efd | Amir Fefer | ```js
|
|
e7c0ad82 | Avi Sharvit | <Fill
|
|
slotId="slot-id"
|
|||
id="some-id"
|
|||
weight={200}
|
|||
overrideProps={{ text: '[Plugin A] this text given by a prop' }}
|
|||
/>
|
|||
27417efd | Amir Fefer | ```
|
|
e7c0ad82 | Avi Sharvit | _plugin B_
|
|
27417efd | Amir Fefer | ||
```js
|
|||
e7c0ad82 | Avi Sharvit | <Fill
|
|
slotId="slot-id"
|
|||
id="some-id"
|
|||
weight={100}
|
|||
overrideProps={{ text: '[Plugin B] this text given by a prop' }}
|
|||
/>
|
|||
27417efd | Amir Fefer | ```
|
|
e7c0ad82 | Avi Sharvit | ||
27417efd | Amir Fefer | In this case, the slot doesn't have `multi` prop, therefore it will take the max weight which is Plugin A's fill.
|
|
#### Global fill
|
|||
e7c0ad82 | Avi Sharvit | ||
27417efd | Amir Fefer | This fill is available on each and every core page
|
|
A plugin should use global fills when it doesn't have access to that area (i.e adding a component in the about page)
|
|||
If a plugin wants to extend foreman's layout, or whether it has a partial in a core page via facets, a regular fill is enough.
|
|||
create a `fills_index.js` file under webpack directory:
|
|||
e7c0ad82 | Avi Sharvit | ||
27417efd | Amir Fefer | ```js
|
|
import React from 'react';
|
|||
import SomeComponent from './components/SomeComponent';
|
|||
import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
|
|||
// if some of the components are connected to redux, registering a reducer is required
|
|||
e7c0ad82 | Avi Sharvit | registerReducer('[plugin]-extends', extendReducer);
|
|
27417efd | Amir Fefer | ||
addGlobalFill('slotId', 'fillId', <SomeComponent key="some-key" />, 300);
|
|||
e7c0ad82 | Avi Sharvit | // instead of a component, you can also override props
|
|
addGlobalFill(
|
|||
'slotId',
|
|||
'fillId',
|
|||
{ someProp: 'this is an override prop' },
|
|||
300
|
|||
);
|
|||
27417efd | Amir Fefer | ```
|
|
41a3edb3 | Jeremy Lenz | Register `fills` global file in `plugin.rb` file:
|
|
27417efd | Amir Fefer | ||
```ruby
|
|||
Foreman::Plugin.register :<plugin> do
|
|||
# content
|
|||
register_global_file 'fills'
|
|||
end
|
|||
```
|
|||
Finally, add a slot in foreman core:
|
|||
```ruby
|
|||
<%= slot('slotId', true) %>
|
|||
```
|