Project

General

Profile

Download (3.29 KB) Statistics
| Branch: | Tag: | Revision:
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) %>
```