@@ -32,7 +32,7 @@ These props accept props of the `Input` component with which you are able to ove
32
32
33
33
<Canvas of = { ComponentStories .WithCustomValidation } sourceState = " none" />
34
34
35
- ** Code Example**
35
+ ### Code Example
36
36
37
37
<details style = { { marginBlockEnd: " 2rem" }} >
38
38
@@ -114,6 +114,246 @@ export const VariantManagementWithCustomValidation = () => {
114
114
115
115
</details >
116
116
117
+ ## Basic VariantManagement Implementation
118
+
119
+ This example shows how a basic implementation of the ` VariantManagement ` inside a ` FilterBar ` could look like. For a more in depth documentation you can take a look at the official [ Fiori for Web Design Guidelines] ( https://experience.sap.com/fiori-design-web/variant-management/ ) .
120
+
121
+ ** Note:** All views are applied automatically, so the "Apply Automatically" checkboxes in both dialogs won't be visible.
122
+
123
+ <Canvas of = { ComponentStories .WithFilterBarImplementation } sourceState = " none" />
124
+
125
+ ### Code Example
126
+
127
+ <details style = { { marginBlockEnd: " 2rem" }} >
128
+
129
+ <summary >Show Code</summary >
130
+
131
+ ``` tsx
132
+ function FilterBarWithVariantManagement() {
133
+ const [selectedVariant, setSelectedVariant] = useState (' Standard' );
134
+ const [defaultVariant, setDefaultVariant] = useState (' Standard' );
135
+ const [customVariants, setCustomVariants] = useState <VariantItemPropTypes []>([]);
136
+ const [isDirty, setIsDirty] = useState (false );
137
+ const [checkIfDiry, setCheckIfDirty] = useState (false );
138
+
139
+ // this should be persisted (e.g. by the local storage of the browser or on the server)
140
+ const initialVariantValues = useRef ({
141
+ Standard: {
142
+ selectedCountry: ' Indonesia' ,
143
+ date: ' ' ,
144
+ selectedCodes: {}
145
+ }
146
+ });
147
+
148
+ const filterReducer = (state , action ) => {
149
+ const { payload, type } = action ;
150
+ setCheckIfDirty (true );
151
+ switch (type ) {
152
+ case ' selectedCountry' :
153
+ return { ... state , selectedCountry: payload };
154
+ case ' date' :
155
+ return { ... state , date: payload };
156
+ case ' selectedCodes' :
157
+ return { ... state , selectedCodes: payload };
158
+ case ' changeVariant' :
159
+ return payload ;
160
+ default :
161
+ console .warn (' Unknown action type!' );
162
+ return state ;
163
+ }
164
+ };
165
+
166
+ const [filters, dispatchFiltersChange] = useReducer (filterReducer , initialVariantValues .current .Standard );
167
+ const { selectedCountry, date, selectedCodes } = filters ;
168
+
169
+ const handleSelectChange = (e ) => {
170
+ const { selectedOption } = e .detail ;
171
+ dispatchFiltersChange ({ type: ' selectedCountry' , payload: selectedOption .textContent });
172
+ };
173
+ const handleDateChange = (e ) => {
174
+ dispatchFiltersChange ({ type: ' date' , payload: e .detail .value });
175
+ };
176
+ const handleSelectedCodesChange = (e ) => {
177
+ dispatchFiltersChange ({
178
+ type: ' selectedCodes' ,
179
+ payload: e .detail .items .reduce ((acc , cur ) => {
180
+ acc [cur .dataset .code ] = true ;
181
+ return acc ;
182
+ }, {})
183
+ });
184
+ };
185
+
186
+ const handleSaveAs = (e ) => {
187
+ const {
188
+ variantItem : _omit,
189
+ selected : _omit2,
190
+ readOnly : _omit3,
191
+ labelReadOnly : _omit4,
192
+ ... variantItemProps
193
+ } = e .detail ;
194
+ if (variantItemProps .isDefault ) {
195
+ setDefaultVariant (variantItemProps .children );
196
+ }
197
+ setCustomVariants ((prev ) => [... prev , { ... variantItemProps , author: ' Current User' }]);
198
+ initialVariantValues .current [variantItemProps .children ] = filters ;
199
+ setSelectedVariant (variantItemProps .children );
200
+ setIsDirty (false );
201
+ };
202
+
203
+ const handleSave = (e ) => {
204
+ const { variantItem : _omit, selected : _omit2, ... variantItemProps } = e .detail ;
205
+ initialVariantValues .current [variantItemProps .children ] = filters ;
206
+ setIsDirty (false );
207
+ };
208
+
209
+ const handleSaveManageViews = (e ) => {
210
+ const { deletedVariants, updatedVariants } = e .detail ;
211
+ deletedVariants .forEach ((variant ) => {
212
+ delete initialVariantValues .current [variant .children ];
213
+ setCustomVariants ((prev ) => prev .filter ((item ) => item .children !== variant .children ));
214
+ });
215
+ updatedVariants .forEach ((variant ) => {
216
+ const { variantItem : _omit, selected : _omit2, ... variantItemProps } = variant ;
217
+ initialVariantValues .current [variant .children ] = variantItemProps ;
218
+ if (variant .isDefault ) {
219
+ setDefaultVariant (variant .children );
220
+ }
221
+ if (variant .selected ) {
222
+ setSelectedVariant (variant .children );
223
+ }
224
+ setCustomVariants ((prev ) => {
225
+ return prev .map ((item ) => {
226
+ if (item .children === variant .prevVariant .children ) {
227
+ return variantItemProps ;
228
+ }
229
+ return item ;
230
+ });
231
+ });
232
+ });
233
+ };
234
+
235
+ const handleSelect = (e ) => {
236
+ const privateSelectedVariant = e .detail .selectedVariant .children ;
237
+ dispatchFiltersChange ({
238
+ type: ' changeVariant' ,
239
+ payload: initialVariantValues .current [privateSelectedVariant ]
240
+ });
241
+ setSelectedVariant (privateSelectedVariant );
242
+ };
243
+
244
+ useEffect (() => {
245
+ if (checkIfDiry ) {
246
+ const hasChanged = Object .entries (initialVariantValues .current [selectedVariant ]).some (([key , val ]) => {
247
+ if (key === ' selectedCodes' ) {
248
+ const selectedCodesLength = Object .keys (filters .selectedCodes ).length ;
249
+ if (selectedCodesLength > 0 && Object .keys (val ).length !== selectedCodesLength ) {
250
+ return true ;
251
+ }
252
+ return Object .entries (filters .selectedCodes ).some (([code , bool ]) => {
253
+ return val [code ] !== bool ;
254
+ });
255
+ }
256
+ return filters [key ] !== val ;
257
+ });
258
+ setCheckIfDirty (false );
259
+ setIsDirty (hasChanged );
260
+ }
261
+ }, [checkIfDiry , selectedVariant ]);
262
+
263
+ return (
264
+ <>
265
+ <FilterBar
266
+ header = {
267
+ <VariantManagement
268
+ hideApplyAutomatically
269
+ dirtyState = { isDirty }
270
+ onSaveAs = { handleSaveAs }
271
+ onSave = { handleSave }
272
+ onSelect = { handleSelect }
273
+ onSaveManageViews = { handleSaveManageViews }
274
+ >
275
+ <VariantItem
276
+ selected = { selectedVariant === ' Standard' }
277
+ global
278
+ isDefault = { defaultVariant === ' Standard' }
279
+ author = " SAP"
280
+ readOnly
281
+ labelReadOnly
282
+ >
283
+ Standard
284
+ </VariantItem >
285
+ { customVariants .map ((variantItemProps ) => {
286
+ return (
287
+ <VariantItem
288
+ key = { variantItemProps .children }
289
+ { ... variantItemProps }
290
+ selected = { selectedVariant === variantItemProps .children }
291
+ isDefault = { defaultVariant === variantItemProps .children }
292
+ >
293
+ { variantItemProps .children }
294
+ </VariantItem >
295
+ );
296
+ })}
297
+ </VariantManagement >
298
+ }
299
+ >
300
+ <FilterGroupItem label = " Countries" >
301
+ <Select onChange = { handleSelectChange } >
302
+ <Option selected = { selectedCountry === ' Indonesia' } >Indonesia</Option >
303
+ <Option selected = { selectedCountry === ' Costa Rica' } >Costa Rica</Option >
304
+ <Option selected = { selectedCountry === ' Slovakia' } >Slovakia</Option >
305
+ <Option selected = { selectedCountry === ' Iceland' } >Iceland</Option >
306
+ <Option selected = { selectedCountry === ' Malta' } >Malta</Option >
307
+ <Option selected = { selectedCountry === ' Guyana' } >Guyana</Option >
308
+ <Option selected = { selectedCountry === ' Spain' } >Spain</Option >
309
+ <Option selected = { selectedCountry === ' Austria' } >Austria</Option >
310
+ </Select >
311
+ </FilterGroupItem >
312
+ <FilterGroupItem label = " Date" >
313
+ <DatePicker value = { date } onChange = { handleDateChange } />
314
+ </FilterGroupItem >
315
+ <FilterGroupItem label = " Company Code" >
316
+ <MultiComboBox onSelectionChange = { handleSelectedCodesChange } >
317
+ <MultiComboBoxItem text = " 001" selected = { selectedCodes [' 001' ]} data-code = " 001" />
318
+ <MultiComboBoxItem text = " 002" selected = { selectedCodes [' 002' ]} data-code = " 002" />
319
+ <MultiComboBoxItem text = " 003" selected = { selectedCodes [' 003' ]} data-code = " 003" />
320
+ <MultiComboBoxItem text = " 004" selected = { selectedCodes [' 004' ]} data-code = " 004" />
321
+ <MultiComboBoxItem text = " 005" selected = { selectedCodes [' 005' ]} data-code = " 005" />
322
+ </MultiComboBox >
323
+ </FilterGroupItem >
324
+ </FilterBar >
325
+ <Form
326
+ style = { { marginBlockStart: ' 2rem' }}
327
+ columnsS = { 1 }
328
+ columnsM = { 1 }
329
+ columnsL = { 1 }
330
+ columnsXL = { 1 }
331
+ labelSpanM = { 2 }
332
+ labelSpanL = { 2 }
333
+ labelSpanXL = { 2 }
334
+ >
335
+ <FormItem label = " Current View" >
336
+ <Text >{ selectedVariant } </Text >
337
+ </FormItem >
338
+ <FormGroup titleText = " Filters" >
339
+ <FormItem label = " Selected Country" >
340
+ <Text >{ selectedCountry } </Text >
341
+ </FormItem >
342
+ <FormItem label = " Selected Date" >
343
+ <Text >{ date } </Text >
344
+ </FormItem >
345
+ <FormItem label = " Selected Company Codes" >
346
+ <Text >{ Object .keys (selectedCodes ).join (' , ' )} </Text >
347
+ </FormItem >
348
+ </FormGroup >
349
+ </Form >
350
+ </>
351
+ );
352
+ }
353
+ ```
354
+
355
+ </details >
356
+
117
357
<Markdown >{ SubcomponentsSection } </Markdown >
118
358
119
359
## VariantItem
0 commit comments