react-jsonschema-form-extras 1.0.0 → 1.1.0-alpha.183650

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,1084 +1,1089 @@
1
- [![Build Status](https://travis-ci.org/RxNT/react-jsonschema-form-extas.svg?branch=master)](https://travis-ci.org/RxNT/react-jsonschema-form-extras)
2
- [![Coverage Status](https://coveralls.io/repos/github/RxNT/react-jsonschema-form-extras/badge.svg)](https://coveralls.io/github/RxNT/react-jsonschema-form-extras)
3
- [![npm version](https://badge.fury.io/js/react-jsonschema-form-extras.svg)](https://badge.fury.io/js/react-jsonschema-form-extras)
4
-
5
- # Catalogue
6
-
7
- This project provides light integration over established React components,
8
- trying to keep configurations compatible with original project.
9
-
10
- All configurations you can specify in original projects, can be reused here.
11
-
12
- - Composite array field (`ui:field` > `compositeArray`)
13
- - Collapsible fields (`ui:field` > `collapsible`)
14
- - Alternative input fields (`ui:field` > `altInput`)
15
- - Typeahead, based on [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead) (`ui:field` > `typeahead`)
16
- - Async Typeahead based on [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead) (`ui:field` > `asyncTypeahead`)
17
- - RTE, based on [react-rte](https://github.com/sstur/react-rte) (`ui:field` > `rte`)
18
- - Tables, based on [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table) (`ui:field` > `table`)
19
- - Multi-typeahead field (`ui:field` > `multiTypeahead`)
20
-
21
- ## Table of Contents
22
-
23
- - [Use](#use)
24
- - [Composite array field (compositeArray)](#composite-array-field-compositearray)
25
- - [Purpose](#purpose)
26
- - [Use](#use)
27
- - [Properties](#properties)
28
- - [Collapsible fields (collapsible)](#collapsible-fields-collapsible)
29
- - [Purpose](#purpose)
30
- - [Use](#use)
31
- - [Properties](#properties)
32
- - [Examples](#examples)
33
- - [Using specific legend in collapsible field.](#using-specific-legend-in-collapsible-field)
34
- - [Properties](#properties)
35
- - [Typeahead, based on react-bootstrap-typeahead (typeahead)](#typeahead-based-on-react-bootstrap-typeahead-typeahead)
36
- - [Purpose](#purpose)
37
- - [Use](#use)
38
- - [Properties](#properties)
39
- - [Label key](#label-key)
40
- - [Mapping](#mapping)
41
- - [Async Typeahead based on react-bootstrap-typeahead (asyncTypeahead)](#async-typeahead-based-on-react-bootstrap-typeahead-asynctypeahead)
42
- - [Purpose](#purpose)
43
- - [Use](#use)
44
- - [Properties](#properties)
45
- - [RTE, based on react-rte (rte)](#rte-based-on-react-rte-rte)
46
- - [Purpose](#purpose)
47
- - [Use](#use)
48
- - [Properties](#properties)
49
- - [Tables, based on react-bootstrap-table (table)](#tables-based-on-react-bootstrap-table-table)
50
- - [Purpose](#purpose)
51
- - [Use](#use)
52
- - [Properties](#properties)
53
- - [Columns order](#columns-order)
54
- - [Cell dataFormat](#cell-dataformat)
55
- - [Additional column actions](#additional-column-actions)
56
- - [Multi-typeahead field (multiTypeahead)](#multi-typeahead-field-multitypeahead)
57
- - [Purpose](#purpose)
58
- - [Recent Changes](#recent-changes)
59
- - [Use](#use)
60
- - [Properties](#properties)
61
- - [Example](#example)
62
- - [Custom Styling](#custom-styling)
63
- - [React Day Picker, based on react-day-picker (rdp)](#react-day-picker-based-on-react-day-picker-rdp)
64
- - [Purpose](#purpose)
65
- - [Use](#use)
66
- - [Properties](#properties)
67
- - [Contribute](#contribute)
68
- - [Support](#support)
69
- - [License](#license)
70
-
71
- ---
72
-
73
- ## Use
74
-
75
- This project uses internal react-jsonschema-form extension mechanism, through ui:field option in uiSchema.
76
- The simplest example of using it out of the box, is like this:
77
-
78
- ```js
79
- import Form from "react-jsonschema-form";
80
- import fields from "react-jsonschema-form-extras";
81
-
82
- ReactDOM.render(<Form fields={fields} />, document.getElementById("app"));
83
- ```
84
-
85
- If you have additional extensions, that are not part of this project, you can enable them, like this
86
-
87
- ```js
88
- import Form from "react-jsonschema-form";
89
- import otherFields from "other-fields";
90
- import fields from "react-jsonschema-form-extras";
91
-
92
- let allFields = Object.assign({}, fields, otherFields);
93
-
94
- ReactDOM.render(<Form fields={allFields} />, document.getElementById("app"));
95
- ```
96
-
97
- You can load only one field you need if want to keep the bundle small.
98
-
99
- ```js
100
- import Form from "react-jsonschema-form";
101
- import { TypeaheadField } from "react-jsonschema-form-extras/lib/TypeaheadField";
102
-
103
- ReactDOM.render(
104
- <Form fields={{ typeahead: TypeaheadField }} />,
105
- document.getElementById("app")
106
- );
107
- ```
108
-
109
- [![Edit p3z45m8rpq](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/p3z45m8rpq)
110
-
111
- If you want multiple fields:
112
-
113
- ```js
114
- import Form from "react-jsonschema-form";
115
- import { TypeaheadField } from "react-jsonschema-form-extras/lib/TypeaheadField";
116
- import ReactDatePicker from "react-jsonschema-form-extras/lib/ReactDatePicker";
117
-
118
- ReactDOM.render(
119
- <Form fields={{ typeahead: TypeaheadField, rdp: ReactDatePicker }} />,
120
- document.getElementById("app")
121
- );
122
- ```
123
-
124
- [![Edit wnyl7n07zk](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/wnyl7n07zk)
125
-
126
- ## Composite array field (`compositeArray`)
127
-
128
- ### Purpose
129
-
130
- This is a simple UI pattern, where you want to separate entering a new value to the array and working with existing values.
131
-
132
- ### Use
133
-
134
- The simplest `uiSchema` configuration would be:
135
-
136
- ```json
137
- {
138
- "ui:field": "compositeArray",
139
- "inputField": "typeahead",
140
- "arrayField": "table",
141
- "typeahead": {},
142
- "table": {}
143
- }
144
- ```
145
-
146
- This means the final field will be presented in 2 parts
147
-
148
- - initial input with `typeahead` field
149
- - array field in `table` form
150
-
151
- You can specify configurations for each field representation independently.
152
-
153
- ### Properties
154
-
155
- There are only 2 properties needed for it to work
156
-
157
- - `inputField` field from form registry to use as a new field input presentation
158
- - `arrayField` field from form registry to use to present existing array values
159
-
160
- ## Collapsible fields (`collapsible`)
161
-
162
- ### Purpose
163
-
164
- Collapsible helps you to hide content, that might take up too much space on the screen an expand it if user wishes.
165
-
166
- ### Use
167
-
168
- The simplest `uiSchema` configuration would be:
169
-
170
- ```json
171
- {
172
- "ui:field": "collapsible",
173
- "collapse": {
174
- "field": "table"
175
- }
176
- }
177
- ```
178
-
179
- This is a hidden `table` field configuration, which will be presented as collapsed `schema` `title` name.
180
-
181
- ### Properties
182
-
183
- You can customize presentation of collapsible field, with "collapse" object in uiSchema
184
-
185
- - `field` `string` an actual hidden field to use
186
- - `collapsed` `boolean` - indicating initial state (default `true`)
187
- - `icon` `object` icons configuration in `enabled` and `disabled` state
188
- - `enabled` `string` icon, when the field is shown (default `glyphicon glyphicon-chevron-down`)
189
- - `disabled` `string` icon, when field is hidden (default `glyphicon glyphicon-chevron-right`)
190
- - `add` `string` icon, to use in place of an add sign (default `glyphicon glyphicon-plus-sign`)
191
- - `separate` `boolean` enable <hr/> after collapse menu (default `true`)
192
- - `wrapClassName` `string` class name to use on a parent collapse menu div (default `lead`)
193
- - `addTo` `string` array field name, to which icon will be added enables an add icon, that will be shown besides collapsible icon
194
- - `addElement` (experimental) representation element for add function (for example if you want to show modal on add icon press, here where this would be)
195
- - `function(schema, uiSchema, onChange)` that returns React Component to render for add function
196
- - `string` `field` definition from `react-jsonschema-form` catalogue
197
- - `actions` (experimental) allows to add additional actions to collapsible menu
198
- - `array` of `objects` that allows to render any kind of `action` you need, which will be sourced from `formContext` `allActions` configuration
199
- - `component` `string` name of the component, that will be sourced from `formContext.allActions` object
200
- - `props` `object` additional properties for rendered component
201
- - `legend` (experimental) allows to add additional information under collapsed field
202
- - `string` text to be rendered under collapsible field
203
- - `object` that allows to render any kind of `legend` you need, which will be sourced from `formContext` `legends` configuration
204
- - `component` `string` name of the component, that will be sourced from `formContext.legends` object
205
- - `props` `object` additional properties for rendered component
206
-
207
- Additional feature of the Collapsible field is to allow adding empty value to hidden `array`, it's enabled with `addTo` feature, which can
208
- be either `self` which assumes that Collapsible field is the target array, or it can be a property field.
209
-
210
- Field `schema` `title` used as a header of the collapsible action.
211
-
212
- ### Examples
213
-
214
- #### Using specific legend in collapsible field.
215
-
216
- Task:
217
-
218
- We have a `firstName` field, which is collapsible and we need to display a `LanguageLegend`, which would notify user of the language to use.
219
-
220
- Solution:
221
-
222
- The simplest configuration with `schema`, `uiSchema` and `formContext` would look something like this
223
-
224
- ```jsx harmony
225
- import React from "react";
226
- import fields from "react-jsonschema-form-extras"
227
-
228
- let schema = {
229
- type: "object",
230
- properties: {
231
- firstName: { type: "string" }
232
- }
233
- }
234
-
235
- let uiSchema = {
236
- firstName: {
237
- "ui:field": "collapsible",
238
- collapse: {
239
- field: "StringField",
240
- legend: {
241
- component: "LanguageLegend",
242
- props: {
243
- language: "EN"
244
- }
245
- }
246
- }
247
- }
248
- }
249
-
250
- let formContext = {
251
- legends: {
252
- LanguageLegend: (props) => (<h1>Expected {props.language} characters</h1>)
253
- }
254
- }
255
-
256
- <Form formContext={formContext} schema={schema} uiSchema={uiSchema} fields={fields}>
257
- ```
258
-
259
- ## Alternative input fields (`altInput`)
260
-
261
- ### Purpose
262
-
263
- You want to enter the same `field` in 2 different ways. For example if a field might be a `string` and `number`
264
-
265
- ### Use
266
-
267
- The simplest configuration would look something like this
268
-
269
- ```json
270
- {
271
- "ui:field": "altInput",
272
- "defInput": "typeahead",
273
- "altInput": "asyncTypeahead",
274
- "typeahead": {},
275
- "asyncTypeahead": {}
276
- }
277
- ```
278
-
279
- In this case user would be able to enter the same field, either by using async typeahead or regular one.
280
-
281
- ### Properties
282
-
283
- In order to configure presentation there are few options
284
-
285
- - `defInput` `string` registry field to use as primary input method
286
- - `altInput` `string` registry field to use as an alternative input method
287
- - `altInputSeparator` `string` string to use in between those 2 presentations
288
-
289
- ## Typeahead, based on [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead) (`typeahead`)
290
-
291
- ### Purpose
292
-
293
- This is a wrap of [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead), which allows you to use this project in your `jsonschema-form`
294
-
295
- ### Use
296
-
297
- The simplest configuration would be
298
-
299
- ```json
300
- {
301
- "ui:field": "typeahead",
302
- "typeahead": {
303
- "options": [{ "state": "New York" }, { "code": "Washington" }],
304
- "labelKey": "state"
305
- }
306
- }
307
- ```
308
-
309
- In this case the typeahead would only have 2 options - `New York` and `Washigton`
310
-
311
- ### Properties
312
-
313
- All properties that you specify under `typeahead` will be used in the original project.
314
-
315
- - `focusOnMount` focusOn typeahead, after it was mounted to page
316
- - `typeahead` all properties that you specify under `typeahead` will be used in the original project.
317
- Additionally, there are few project specific properties
318
- - `labelKey` have more flexibility in configuration
319
- - `labelKey` `string` used a labelKey in [typeahead](https://github.com/ericgio/react-bootstrap-typeahead) project
320
- - `labelKey` `array` in this case array is a list of fields in original object, which are combined in a single string with a space separator
321
- - `labelKey` `object` with `fields` `array` of fields to use, `separator` string separator to use between fields
322
- - `cleanAfterSelection` `boolean` clean selection after component was selected (default false)
323
- - `mapping` `object` that maps selected object to schema object
324
-
325
- For complete list of configurations refer to [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead)
326
-
327
- Here are some use case examples
328
-
329
- With following options
330
-
331
- ```json
332
- [
333
- {
334
- "name": "Adventures of Huckleberry Finn",
335
- "author": "Mark Twain"
336
- },
337
- {
338
- "name": "The Adventures of Tom Sawyer",
339
- "author": "Mark Twain"
340
- }
341
- ]
342
- ```
343
-
344
- #### Label key
345
-
346
- With labelKey `name` there will be 2 options
347
-
348
- - `Adventures of Huckleberry Finn`
349
- - `The Adventures of Tom Sawyer`
350
-
351
- With labelKey `[ "author", "name" ]`, options will be
352
-
353
- - `Mark Twain Adventures of Huckleberry Finn`
354
- - `Mark Twain The Adventures of Tom Sawyer`
355
-
356
- With lableKey `{ fields: [ "author", "name" ], separator: " - " }`, options will be
357
-
358
- - `Mark Twain - Adventures of Huckleberry Finn`
359
- - `Mark Twain - The Adventures of Tom Sawyer`
360
-
361
- #### Mapping
362
-
363
- Mapping can be one of
364
-
365
- - not specified, in this case selection is sent to the formData as is
366
- - `string` which is field name in typeahead selected object
367
- - `object` with fields corresponding to final schema fields and values, corresponding to fields in typeahead
368
- - `function` which will be called with typeahead selected objects, which ever value you specify will be used
369
-
370
- Mapping as undefined (we accept values as is)
371
-
372
- ```
373
- {
374
- "mapping": undefined
375
- }
376
- ```
377
-
378
- would result in
379
-
380
- - `{ "name": "Adventures of Huckleberry Finn", "author": "Mark Twain" }`
381
- - `{ "name": "The Adventures of Tom Sawyer", "author": "Mark Twain" }`
382
-
383
- Mapping as string (we want only name of the book)
384
-
385
- ```json
386
- {
387
- "mapping": "name"
388
- }
389
- ```
390
-
391
- would result in
392
-
393
- - `"Adventures of Huckleberry Finn"`
394
- - `"The Adventures of Tom Sawyer"`
395
-
396
- Mapping as object (we want to change mapping to creator and book)
397
-
398
- ```json
399
- {
400
- "mapping": {
401
- "creator": "author",
402
- "book": "name"
403
- }
404
- }
405
- ```
406
-
407
- would result in
408
-
409
- - `{ book: "Adventures of Huckleberry Finn", creator: "Mark Twain" }`
410
- - `{ book: "The Adventures of Tom Sawyer", creator: "Mark Twain" }`
411
-
412
- Mapping as function (let's say we want to take a first name of the author)
413
-
414
- ```js
415
- let uiSchema = {
416
- mapping: (event) => event.creator.split(" ")[0]
417
- };
418
- ```
419
-
420
- would result in
421
-
422
- - `"Mark"`
423
- - `"Mark"`
424
-
425
- ## Async Typeahead based on [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead) (`asyncTypeahead`)
426
-
427
- ### Purpose
428
-
429
- This is a wrap around `async` functionality of [typeahead](https://github.com/ericgio/react-bootstrap-typeahead), supporting some additional defaults.
430
-
431
- ### Use
432
-
433
- The simplest configuration would be
434
-
435
- ```json
436
- {
437
- "ui:field": "asyncTypeahead",
438
- "asyncTypeahead": {
439
- "url": "https://example.com/state"
440
- }
441
- }
442
- ```
443
-
444
- This will result in typeahead search with `https://example.com/state?query=${query}`
445
-
446
- ### Properties
447
-
448
- Async typeahead extends default configuration list for `typeahead`, by adding few properties under `asyncTypeahead`
449
-
450
- - `focusOnMount` focusOn typeahead, after it was mounted to page
451
- - `asyncTypeahead` all properties that you specify under `typeahead` will be used in the original project.
452
- - `url` search url, that will be used during autocomplete
453
- - `search` function that will be querying server for data, which takes 2 parameters, and must return a Promise with a json result
454
- - `url` configured URL
455
- - `query` typed query string
456
- - `optionsPath` path to options array in response
457
- - `labelKey` have more flexibility in configuration
458
- - `labelKey` `string` used a labelKey in [typeahead](https://github.com/ericgio/react-bootstrap-typeahead) project
459
- - `labelKey` `array` in this case array is a list of fields in original object, which are combined in a single string with a space separator
460
- - `labelKey` `object` with `fields` `array` of fields to use, `separator` string separator to use between fields
461
- - `cleanAfterSelection` `boolean` clean selection after component was selected (default false)
462
- - `overrideOptions` if true, the user can type any text in the input field (or select an option, then modify it),
463
- and it will be saved in the RJSF model (default false)
464
- - `mapping` `object` that maps selected object to schema object
465
-
466
- For example, let's consider query with `Was` on `url` `https://example.com/state`.
467
-
468
- By default field will query results with - `https://example.com/state?query=Was`.
469
-
470
- Let's say we want to override it and query - `https://example.com/state?name=Was&maxSize=1`.
471
-
472
- Here is how we can do that:
473
-
474
- ```js
475
- let uiSchema = {
476
- "ui:field": "asyncTypeahead",
477
- asyncTypeahead: {
478
- url: "https://example.com/state",
479
- search: (url, query) => fetch(`${url}?name=${query}&maxSize=1`)
480
- }
481
- };
482
- ```
483
-
484
- That is it.
485
-
486
- For complete list of async typeahead configurations refer to [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead)
487
-
488
- ## RTE, based on [react-rte](https://github.com/sstur/react-rte) (`rte`)
489
-
490
- ### Purpose
491
-
492
- This is a simple field, that allows you to enter RTE text inside your string field.
493
-
494
- ### Use
495
-
496
- The simplest configuration would be
497
-
498
- ```json
499
- {
500
- "ui:field": "rte",
501
- "rte": {
502
- "format": "html"
503
- }
504
- }
505
- ```
506
-
507
- ### Properties
508
-
509
- The only property this field requires is `format`
510
-
511
- - `format` `string` an `rte` output format (default `html`)
512
- - `updateOnBlur` `boolean` allows for RTE update parent form only after edit finished, to minimize calculations and redraw (default `false`)
513
-
514
- As with other projects, all configurations, that you'll configure under `uiSchema` `rte` field will be transferred to the actual component.
515
-
516
- ## Tables, based on [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table) (`table`)
517
-
518
- ### Purpose
519
-
520
- This component wraps [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table) for array components, with smart default configurations.
521
-
522
- ### Use
523
-
524
- The simplest configuration would be
525
-
526
- ```json
527
- {
528
- "ui:field": "table"
529
- }
530
- ```
531
-
532
- ### Properties
533
-
534
- You can use `table` field without any predefined configurations, it will generate default table schema with columns.
535
-
536
- - `tableCols` an array of react-bootstrap-table configurations, that override default generated configurations for the field.
537
- - `focusOnAdd` column number, when set, adding new row to the table, it will focus on a specified column.
538
-
539
- By default table component will generate table columns, based on an array schema, with editables, based on field types.
540
-
541
- You can reuse react-jsonschema-form Components, in table column editing, to do that, you need to define
542
-
543
- - `field` property in tableCols override section, with `uiSchema` to use for the field.
544
-
545
- For example let's say we have allergy array, with `allergyName` coming from server source,
546
- we can enable `asyncTypeahead` on allergyName field in `tableCols` override like this:
547
-
548
- ```js
549
- let uiSchema = {
550
- allergies: {
551
- classNames: "col-md-12",
552
- "ui:field": "table",
553
- table: {
554
- tableCols: [
555
- {
556
- dataField: "allergyName",
557
- field: "asyncTypeahead",
558
- uiSchema: {
559
- "ui:field": "asyncTypeahead",
560
- asyncTypeahead: {
561
- bodyContainer: true,
562
- url: "/allergies/typeahead"
563
- }
564
- }
565
- }
566
- ]
567
- }
568
- }
569
- };
570
- ```
571
-
572
- #### Columns order
573
-
574
- By default order of columns is defined by `schema` properties field order.
575
- It might be not always reliable, so there is a way to override it.
576
- By default the order will follow order of columns in `tableCols` configuration.
577
-
578
- ```js
579
- let schema = {
580
- type: "object",
581
- properties: {
582
- medications: {
583
- type: "array",
584
- items: {
585
- type: "object",
586
- properties: {
587
- dosage: { type: "number" },
588
- name: { type: "string" }
589
- }
590
- }
591
- }
592
- }
593
- };
594
-
595
- let uiSchema = {
596
- medications: {
597
- "ui:field": "table",
598
- table: {
599
- tableCols: [
600
- {
601
- dataField: "name"
602
- },
603
- {
604
- dataField: "dosage"
605
- }
606
- ]
607
- }
608
- }
609
- };
610
- ```
611
-
612
- Here although in medications property schema `dosage` goes before `name`, it will be shown first due to `tableCols` order of columns.
613
-
614
- #### Cell dataFormat
615
-
616
- react-bootstrap-table provides custom [dataFormat](https://allenfang.github.io/react-bootstrap-table/docs.html#dataFormat) for rendering data in columns.
617
- We needed to support serialized configuration, so we extended native functionality, with string configuration,
618
-
619
- - `object` dataFormat can be a `string` which translates into field name in the object.
620
- - `date-time` & `date` `string` dataFormat is a format of string presentation, that is generated with moment.js
621
-
622
- For example, let's say we have an allergies table, with identifier, which consists of some numeric id and string name. When showing to the user, we want to show only name. Here is how we can do this:
623
-
624
- ```js
625
- let schema = {
626
- type: "object",
627
- properties: {
628
- allergies: {
629
- type: "array",
630
- items: {
631
- type: "object",
632
- properties: {
633
- identified: {
634
- type: "object",
635
- properties: {
636
- id: { type: "string" },
637
- name: { type: "string" }
638
- }
639
- },
640
- added: { type: "date-time" }
641
- }
642
- }
643
- }
644
- }
645
- };
646
-
647
- let uiSchema = {
648
- medications: {
649
- "ui:field": "table",
650
- table: {
651
- tableCols: [
652
- {
653
- dataField: "identifier",
654
- dataFormat: "name"
655
- },
656
- {
657
- dataField: "dosage",
658
- dataFormat: "YYYY-MM-DD"
659
- }
660
- ]
661
- }
662
- }
663
- };
664
- ```
665
-
666
- In this case dataFormat on identifier field, will translate into selecting name field in identifier object.
667
-
668
- ### Additional column actions
669
-
670
- If you need to define additional column actions to the left or to the right of column content you can do that in
671
- a standard way with `uiSchema` with `leftActions` or `rightActions` defined
672
-
673
- ```js
674
- let uiSchema = {
675
- table: {
676
- leftActions: [
677
- {
678
- action: "delete",
679
- className: "col-md-1",
680
- columnClassName: "col-md-1",
681
- editColumnClassName: "col-md-1",
682
- icon: "glyphicon glyphicon-minus"
683
- }
684
- ],
685
- rightActions: [
686
- {
687
- action: "delete",
688
- icon: "glyphicon glyphicon-minus",
689
- text: "Remove"
690
- }
691
- ]
692
- }
693
- };
694
- ```
695
-
696
- Both left and right actions can accept full column configuration, that will be appended to the rendered column,
697
-
698
- For example, to define delete on each column, you can:
699
-
700
- ```js
701
- let uiSchema = {
702
- table: {
703
- leftActions: [
704
- {
705
- dataField: "delete-button",
706
- dataFormat: (cell, row, enumObject, rowIndex, formData, onChange) => (
707
- <span
708
- onClick={() => onChange(formData.filter((el, i) => rowIndex !== i))}
709
- >
710
- "Remove All"
711
- </span>
712
- ),
713
- editable: false,
714
- displayName: "Left Panel"
715
- }
716
- ],
717
- rightActions: [
718
- {
719
- action: "delete",
720
- icon: "glyphicon glyphicon-minus",
721
- text: "Delete",
722
- displayName: "Right Panel"
723
- }
724
- ]
725
- }
726
- };
727
- ```
728
-
729
- In left panel, we have defined delete with a standard `react-bootstrap-table` format, the only difference is dataFormat signature changed,
730
- appending original formData and onChange callback to relay changes to the listening component.
731
-
732
- Right panel is defined with small syntactic sugar to simpify action defintion
733
-
734
- - `action` can be either `delete` string or function, that is equivalent on onClick function with `cell`, `row`, `enumObject`, `rowIndex`, `formData`, `onChange` parameters
735
- - `icon` icon to use for the column
736
- - `text` text to use for the column
737
- - `displayName` column name
738
-
739
- ## Multi-typeahead field (`multiTypeahead`)
740
-
741
- ### Purpose
742
-
743
- This component provides a multi-typeahead dropdown using Material-UI components with multiple selection enabled. It allows users to search and select multiple options, displaying them as chips/tags, and integrates with react-jsonschema-form. Compatible with react-jsonschema-form.
744
-
745
- ### Recent Changes
746
-
747
- - **BREAKING CHANGE**: Renamed from `MultiSelectField` to `MultiTypeaheadField`
748
- - **Field Name**: Changed from `ui:field: "multiSelect"` to `ui:field: "multiTypeahead"`
749
- - **Configuration**: Changed from `multiSelect: {}` to `multiTypeahead: {}` in uiSchema
750
- - Uses Material-UI components for multi-typeahead functionality.
751
- - All styling (border, label, placeholder, chip, dropdown options, icons) is handled via JSS (`withStyles`).
752
- - Consistent color for label, placeholder, dropdown options, chips, and icons.
753
- - Placeholder and label are always centered and use color `#003B5CBF`.
754
- - Chips use background `#00629B` and white text; delete icon is white.
755
- - Dropdown and clear icons use dark blue (`#00629B`).
756
- - Input and chip layout is compact, with no extra lines or spacing.
757
- - Fixed chip grey appearance on click/hover with proper state overrides.
758
- - Fixed React key prop issues to prevent visual glitches when deleting chips.
759
-
760
- ### Use
761
-
762
- The simplest `uiSchema` configuration would be:
763
-
764
- ```json
765
- {
766
- "ui:field": "multiTypeahead",
767
- "multiTypeahead": {
768
- "options": [
769
- { "label": "Option 1", "value": "opt1" },
770
- { "label": "Option 2", "value": "opt2" }
771
- ],
772
- "label": "Choose options",
773
- "placeholder": "Select..."
774
- }
775
- }
776
- ```
777
-
778
- ### Properties
779
-
780
- All properties are configured under the `multiTypeahead` object in uiSchema:
781
-
782
- - `options` (array): Static list of options to display. Can be an array of objects or strings.
783
- - `url` (string): URL for API-based options. When provided, options will be fetched dynamically based on user input with 300ms debounce.
784
- - `search` (function): Custom search function that overrides the default fetch behavior. Takes `(url, query, queryKey)` parameters and must return a Promise.
785
- - `queryKey` (string): Query parameter key used in API requests (default: "query"). For example, with `queryKey: "search"`, the URL becomes `${url}?search=${query}`.
786
- - `optionsPath` (string): Path to extract options array from API response. Use dot notation for nested properties (e.g., `"data.results"`, `"response.items"`).
787
- - `label` (string): Optional label for the field.
788
- - `placeholder` (string): Optional placeholder text (default: "Select...").
789
- - `labelTemplate` (string): Template for displaying option labels. Use `{fieldName}` syntax to reference object properties (e.g., `"{name} - {category}"`).
790
- - `valueKeys` (array): Array of keys to extract from selected options for the form value (default: `["value"]`). **Note**: When using nested property paths (e.g., `"user.profile.name"`), only the last part of the key chain (`"name"`) will be used as the property name in the resulting value object.
791
-
792
- ### Key Features
793
-
794
- - **Dual Mode Support**: Works with both static options and dynamic API-based options
795
- - **Template Labels**: Use `labelTemplate` to customize how options are displayed
796
- - **Flexible Values**: `valueKeys` allows you to control which properties are saved in the form data
797
- - **Nested API Responses**: Use `optionsPath` to extract options from complex API response structures
798
- - **Custom Query Parameters**: Use `queryKey` to customize the API query parameter name
799
- - **Search & Filter**: For static options, filters locally; for URL-based options, searches via API
800
- - **Debounced API Calls**: 300ms debounce prevents excessive API requests during typing
801
- - **Persistent Selections**: Selected values remain visible even when not in current search results
802
- - **Clear Functionality**: Clear individual chips or all selections at once
803
- - **Loading States**: Shows loading indicator during API calls
804
- - **Keyboard Accessible**: Full keyboard navigation support
805
- - **Click-away Handling**: Dropdown closes when clicking outside the component
806
-
807
- ### Example
808
-
809
- #### Static Options Example
810
-
811
- ```js
812
- import Form from "react-jsonschema-form";
813
- import { MultiTypeaheadField } from "react-jsonschema-form-extras/lib/MultiTypeaheadField";
814
-
815
- const fields = { multiTypeahead: MultiTypeaheadField };
816
-
817
- const schema = {
818
- type: "object",
819
- properties: {
820
- fruits: {
821
- type: "array",
822
- items: { type: "object" }
823
- }
824
- }
825
- };
826
-
827
- const uiSchema = {
828
- fruits: {
829
- "ui:field": "multiTypeahead",
830
- multiTypeahead: {
831
- options: [
832
- { name: "Apple", category: "Tree Fruit", value: "apple", id: 1 },
833
- { name: "Banana", category: "Tropical", value: "banana", id: 2 },
834
- { name: "Cherry", category: "Stone Fruit", value: "cherry", id: 3 }
835
- ],
836
- label: "Select Fruits",
837
- placeholder: "Choose fruits...",
838
- labelTemplate: "{name} - {category}",
839
- valueKeys: ["id", "value", "name"]
840
- }
841
- }
842
- };
843
-
844
- <Form schema={schema} uiSchema={uiSchema} fields={fields} />;
845
- ```
846
-
847
- #### Dynamic/API-based Options Example
848
-
849
- ```js
850
- const uiSchema = {
851
- medications: {
852
- "ui:field": "multiTypeahead",
853
- multiTypeahead: {
854
- url: "/api/medications/search",
855
- queryKey: "search", // Use "search" instead of default "query"
856
- optionsPath: "data.medications", // Extract from nested response
857
- label: "Select Medications",
858
- placeholder: "Type to search medications...",
859
- labelTemplate: "{name} ({strength})",
860
- valueKeys: ["id", "name"],
861
- // Optional custom search function
862
- search: (url, query, queryKey) => {
863
- return fetch(
864
- `${url}?${queryKey}=${encodeURIComponent(query)}&limit=20`
865
- ).then((res) => res.json());
866
- // No need to extract data.results here, optionsPath will handle it
867
- }
868
- }
869
- }
870
- };
871
-
872
- // Without queryKey specified (defaults to "query") but with optionsPath
873
- const uiSchemaWithOptionsPath = {
874
- users: {
875
- "ui:field": "multiTypeahead",
876
- multiTypeahead: {
877
- url: "/api/users/search", // Will call: /api/users/search?query=userInput
878
- optionsPath: "response.users", // Extract from { response: { users: [...] } }
879
- labelTemplate: "{firstName} {lastName}",
880
- valueKeys: ["id", "username"]
881
- }
882
- }
883
- };
884
-
885
- // Simple case - API returns array directly (no optionsPath needed)
886
- const uiSchemaDefault = {
887
- tags: {
888
- "ui:field": "multiTypeahead",
889
- multiTypeahead: {
890
- url: "/api/tags/search", // API returns: [{ name: "tag1" }, { name: "tag2" }]
891
- labelTemplate: "{name}",
892
- valueKeys: ["id", "name"]
893
- }
894
- }
895
- };
896
- ```
897
-
898
- #### Simple String Array Example
899
-
900
- ```js
901
- const schema = {
902
- type: "object",
903
- properties: {
904
- tags: {
905
- type: "array",
906
- items: { type: "string" }
907
- }
908
- }
909
- };
910
-
911
- const uiSchema = {
912
- tags: {
913
- "ui:field": "multiTypeahead",
914
- multiTypeahead: {
915
- options: ["JavaScript", "React", "Node.js", "Python", "Java"],
916
- label: "Programming Languages",
917
- placeholder: "Select languages..."
918
- }
919
- }
920
- };
921
- ```
922
-
923
- #### ValueKeys with Nested Properties Example
924
-
925
- ```js
926
- // Options with nested properties
927
- const options = [
928
- {
929
- user: { profile: { name: "John Doe" }, id: 123 },
930
- department: { info: { title: "Engineering" } },
931
- role: "Developer"
932
- }
933
- ];
934
-
935
- const uiSchema = {
936
- employees: {
937
- "ui:field": "multiTypeahead",
938
- multiTypeahead: {
939
- options: options,
940
- labelTemplate: "{user.profile.name} - {role}",
941
- valueKeys: [
942
- "user.profile.name",
943
- "user.id",
944
- "department.info.title",
945
- "role"
946
- ]
947
- }
948
- }
949
- };
950
-
951
- // Resulting value object for selected option will be:
952
- // {
953
- // name: "John Doe", // from user.profile.name (uses last part: "name")
954
- // id: 123, // from user.id (uses last part: "id")
955
- // title: "Engineering", // from department.info.title (uses last part: "title")
956
- // role: "Developer" // from role (uses last part: "role")
957
- // }
958
- ```
959
-
960
- ### Custom Styling
961
-
962
- All styles are handled via JSS (`withStyles`) in the component. The styling is designed to be consistent and follows Material-UI design patterns with custom color overrides:
963
-
964
- **Input Field:**
965
-
966
- - Border color: `#DFE6EB`
967
- - Font family: Mulish
968
- - Input text color: `#003B5C`
969
- - Label/placeholder color: `#003B5CBF`
970
- - Minimum height: 56px with centered alignment
971
-
972
- **Chips (Selected Items):**
973
-
974
- - Background: `#00629B` (blue)
975
- - Text color: White
976
- - Delete icon: White
977
- - Font: Mulish, 12px
978
- - Proper state handling for hover/focus/active states
979
-
980
- **Dropdown:**
981
-
982
- - Background: White
983
- - Border: `#DFE6EB`
984
- - Border radius: 4px (bottom only)
985
- - Box shadow: `0 2px 8px rgba(0,0,0,0.1)`
986
- - Max height: 200px with scroll
987
- - Option hover: `#f5f5f5`
988
-
989
- **Icons:**
990
-
991
- - Dropdown indicator: `#00629B`
992
- - Clear button: `#00629B`
993
- - Loading indicator: Displays during API calls
994
-
995
- **Layout:**
996
-
997
- - Chips and input field are properly aligned in a flex container
998
- - Input field takes remaining space with minimum 120px width
999
- - Clear button appears when selections exist
1000
- - Compact layout with optimized spacing
1001
-
1002
- To customize styling, edit the `styles` object in `MultiTypeaheadField.js` using JSS syntax.
1003
-
1004
- ## React Day Picker, based on [react-day-picker](https://github.com/gpbl/react-day-picker) (`rdp`)
1005
-
1006
- ### Purpose
1007
-
1008
- Allows you to use react-day-picker as input `ui:field`. This component works only with `string` formatted as `date` and `date-time`.
1009
-
1010
- ### Use
1011
-
1012
- The simplest configuration would be
1013
-
1014
- ```json
1015
- {
1016
- "ui:field": "rdp"
1017
- }
1018
- ```
1019
-
1020
- ### Properties
1021
-
1022
- All configurations, that you'll configure under `uiSchema` `rdp` field will be transferred to the actual component.
1023
-
1024
- For example to enable `Today` button, you would need to specify following uiSchema
1025
-
1026
- ```json
1027
- {
1028
- "ui:field": "rdp",
1029
- "rdp": {
1030
- "dayPickerProps": {
1031
- "todayButton": "Today"
1032
- }
1033
- }
1034
- }
1035
- ```
1036
-
1037
- For the full list of properties refer to [React Day Picker](http://react-day-picker.js.org).
1038
-
1039
- ## Table Expandable Row Component
1040
-
1041
- ### Purpose
1042
-
1043
- to enable expandable row in table component
1044
-
1045
- ### Use
1046
-
1047
- to expand table rows
1048
-
1049
- ```json
1050
- {
1051
- "table": {
1052
- "isTableExpandable": false,
1053
- "allowOneRowExpanding": true
1054
- }
1055
- }
1056
- ```
1057
-
1058
- ### Properties
1059
-
1060
- All configurations, that you'll configure under `uiSchema` `table` field will be transferred to the actual component.
1061
-
1062
- For example to enable `ExpandRow` button, you would need to specify following uiSchema
1063
-
1064
- ```json
1065
- {
1066
- "table": {
1067
- "isTableExpandable": false,
1068
- "allowOneRowExpanding": true
1069
- }
1070
- }
1071
- ```
1072
-
1073
- ## Contribute
1074
-
1075
- - Issue Tracker: github.com/RxNT/react-jsonschema-extras/issues
1076
- - Source Code: github.com/RxNT/react-jsonschema-extras
1077
-
1078
- ## Support
1079
-
1080
- If you are having issues, please let us know here or on StackOverflow.
1081
-
1082
- ## License
1083
-
1084
- The project is licensed under the Apache Licence 2.0.
1
+ [![Build Status](https://travis-ci.org/RxNT/react-jsonschema-form-extas.svg?branch=master)](https://travis-ci.org/RxNT/react-jsonschema-form-extras)
2
+ [![Coverage Status](https://coveralls.io/repos/github/RxNT/react-jsonschema-form-extras/badge.svg)](https://coveralls.io/github/RxNT/react-jsonschema-form-extras)
3
+ [![npm version](https://badge.fury.io/js/react-jsonschema-form-extras.svg)](https://badge.fury.io/js/react-jsonschema-form-extras)
4
+
5
+ # Catalogue
6
+
7
+ This project provides light integration over established React components,
8
+ trying to keep configurations compatible with original project.
9
+
10
+ All configurations you can specify in original projects, can be reused here.
11
+
12
+ - Composite array field (`ui:field` > `compositeArray`)
13
+ - Collapsible fields (`ui:field` > `collapsible`)
14
+ - Alternative input fields (`ui:field` > `altInput`)
15
+ - Typeahead, based on [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead) (`ui:field` > `typeahead`)
16
+ - Async Typeahead based on [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead) (`ui:field` > `asyncTypeahead`)
17
+ - RTE, based on [react-rte](https://github.com/sstur/react-rte) (`ui:field` > `rte`)
18
+ - Tables, based on [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table) (`ui:field` > `table`)
19
+ - Multi-typeahead field (`ui:field` > `multiTypeahead`)
20
+
21
+ ## Table of Contents
22
+
23
+ - [Use](#use)
24
+ - [Composite array field (compositeArray)](#composite-array-field-compositearray)
25
+ - [Purpose](#purpose)
26
+ - [Use](#use)
27
+ - [Properties](#properties)
28
+ - [Collapsible fields (collapsible)](#collapsible-fields-collapsible)
29
+ - [Purpose](#purpose)
30
+ - [Use](#use)
31
+ - [Properties](#properties)
32
+ - [Examples](#examples)
33
+ - [Using specific legend in collapsible field.](#using-specific-legend-in-collapsible-field)
34
+ - [Properties](#properties)
35
+ - [Typeahead, based on react-bootstrap-typeahead (typeahead)](#typeahead-based-on-react-bootstrap-typeahead-typeahead)
36
+ - [Purpose](#purpose)
37
+ - [Use](#use)
38
+ - [Properties](#properties)
39
+ - [Label key](#label-key)
40
+ - [Mapping](#mapping)
41
+ - [Async Typeahead based on react-bootstrap-typeahead (asyncTypeahead)](#async-typeahead-based-on-react-bootstrap-typeahead-asynctypeahead)
42
+ - [Purpose](#purpose)
43
+ - [Use](#use)
44
+ - [Properties](#properties)
45
+ - [RTE, based on react-rte (rte)](#rte-based-on-react-rte-rte)
46
+ - [Purpose](#purpose)
47
+ - [Use](#use)
48
+ - [Properties](#properties)
49
+ - [Tables, based on react-bootstrap-table (table)](#tables-based-on-react-bootstrap-table-table)
50
+ - [Purpose](#purpose)
51
+ - [Use](#use)
52
+ - [Properties](#properties)
53
+ - [Columns order](#columns-order)
54
+ - [Cell dataFormat](#cell-dataformat)
55
+ - [Additional column actions](#additional-column-actions)
56
+ - [Multi-typeahead field (multiTypeahead)](#multi-typeahead-field-multitypeahead)
57
+ - [Purpose](#purpose)
58
+ - [Recent Changes](#recent-changes)
59
+ - [Use](#use)
60
+ - [Properties](#properties)
61
+ - [Example](#example)
62
+ - [Custom Styling](#custom-styling)
63
+ - [React Day Picker, based on react-day-picker (rdp)](#react-day-picker-based-on-react-day-picker-rdp)
64
+ - [Purpose](#purpose)
65
+ - [Use](#use)
66
+ - [Properties](#properties)
67
+ - [Contribute](#contribute)
68
+ - [Support](#support)
69
+ - [License](#license)
70
+
71
+ ---
72
+
73
+ ## Use
74
+
75
+ This project uses internal react-jsonschema-form extension mechanism, through ui:field option in uiSchema.
76
+ The simplest example of using it out of the box, is like this:
77
+
78
+ ```js
79
+ import Form from "react-jsonschema-form";
80
+ import fields from "react-jsonschema-form-extras";
81
+
82
+ ReactDOM.render(<Form fields={fields} />, document.getElementById("app"));
83
+ ```
84
+
85
+ If you have additional extensions, that are not part of this project, you can enable them, like this
86
+
87
+ ```js
88
+ import Form from "react-jsonschema-form";
89
+ import otherFields from "other-fields";
90
+ import fields from "react-jsonschema-form-extras";
91
+
92
+ let allFields = Object.assign({}, fields, otherFields);
93
+
94
+ ReactDOM.render(<Form fields={allFields} />, document.getElementById("app"));
95
+ ```
96
+
97
+ You can load only one field you need if want to keep the bundle small.
98
+
99
+ ```js
100
+ import Form from "react-jsonschema-form";
101
+ import { TypeaheadField } from "react-jsonschema-form-extras/lib/TypeaheadField";
102
+
103
+ ReactDOM.render(
104
+ <Form fields={{ typeahead: TypeaheadField }} />,
105
+ document.getElementById("app")
106
+ );
107
+ ```
108
+
109
+ [![Edit p3z45m8rpq](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/p3z45m8rpq)
110
+
111
+ If you want multiple fields:
112
+
113
+ ```js
114
+ import Form from "react-jsonschema-form";
115
+ import { TypeaheadField } from "react-jsonschema-form-extras/lib/TypeaheadField";
116
+ import ReactDatePicker from "react-jsonschema-form-extras/lib/ReactDatePicker";
117
+
118
+ ReactDOM.render(
119
+ <Form fields={{ typeahead: TypeaheadField, rdp: ReactDatePicker }} />,
120
+ document.getElementById("app")
121
+ );
122
+ ```
123
+
124
+ [![Edit wnyl7n07zk](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/wnyl7n07zk)
125
+
126
+ ## Composite array field (`compositeArray`)
127
+
128
+ ### Purpose
129
+
130
+ This is a simple UI pattern, where you want to separate entering a new value to the array and working with existing values.
131
+
132
+ ### Use
133
+
134
+ The simplest `uiSchema` configuration would be:
135
+
136
+ ```json
137
+ {
138
+ "ui:field": "compositeArray",
139
+ "inputField": "typeahead",
140
+ "arrayField": "table",
141
+ "typeahead": {},
142
+ "table": {}
143
+ }
144
+ ```
145
+
146
+ This means the final field will be presented in 2 parts
147
+
148
+ - initial input with `typeahead` field
149
+ - array field in `table` form
150
+
151
+ You can specify configurations for each field representation independently.
152
+
153
+ ### Properties
154
+
155
+ There are only 2 properties needed for it to work
156
+
157
+ - `inputField` field from form registry to use as a new field input presentation
158
+ - `arrayField` field from form registry to use to present existing array values
159
+
160
+ ## Collapsible fields (`collapsible`)
161
+
162
+ ### Purpose
163
+
164
+ Collapsible helps you to hide content, that might take up too much space on the screen an expand it if user wishes.
165
+
166
+ ### Use
167
+
168
+ The simplest `uiSchema` configuration would be:
169
+
170
+ ```json
171
+ {
172
+ "ui:field": "collapsible",
173
+ "collapse": {
174
+ "field": "table"
175
+ }
176
+ }
177
+ ```
178
+
179
+ This is a hidden `table` field configuration, which will be presented as collapsed `schema` `title` name.
180
+
181
+ ### Properties
182
+
183
+ You can customize presentation of collapsible field, with "collapse" object in uiSchema
184
+
185
+ - `field` `string` an actual hidden field to use
186
+ - `collapsed` `boolean` - indicating initial state (default `true`)
187
+ - `icon` `object` icons configuration in `enabled` and `disabled` state
188
+ - `enabled` `string` icon, when the field is shown (default `glyphicon glyphicon-chevron-down`)
189
+ - `disabled` `string` icon, when field is hidden (default `glyphicon glyphicon-chevron-right`)
190
+ - `add` `string` icon, to use in place of an add sign (default `glyphicon glyphicon-plus-sign`)
191
+ - `separate` `boolean` enable <hr/> after collapse menu (default `true`)
192
+ - `wrapClassName` `string` class name to use on a parent collapse menu div (default `lead`)
193
+ - `addTo` `string` array field name, to which icon will be added enables an add icon, that will be shown besides collapsible icon
194
+ - `addElement` (experimental) representation element for add function (for example if you want to show modal on add icon press, here where this would be)
195
+ - `function(schema, uiSchema, onChange)` that returns React Component to render for add function
196
+ - `string` `field` definition from `react-jsonschema-form` catalogue
197
+ - `actions` (experimental) allows to add additional actions to collapsible menu
198
+ - `array` of `objects` that allows to render any kind of `action` you need, which will be sourced from `formContext` `allActions` configuration
199
+ - `component` `string` name of the component, that will be sourced from `formContext.allActions` object
200
+ - `props` `object` additional properties for rendered component
201
+ - `legend` (experimental) allows to add additional information under collapsed field
202
+ - `string` text to be rendered under collapsible field
203
+ - `object` that allows to render any kind of `legend` you need, which will be sourced from `formContext` `legends` configuration
204
+ - `component` `string` name of the component, that will be sourced from `formContext.legends` object
205
+ - `props` `object` additional properties for rendered component
206
+
207
+ Additional feature of the Collapsible field is to allow adding empty value to hidden `array`, it's enabled with `addTo` feature, which can
208
+ be either `self` which assumes that Collapsible field is the target array, or it can be a property field.
209
+
210
+ Field `schema` `title` used as a header of the collapsible action.
211
+
212
+ ### Examples
213
+
214
+ #### Using specific legend in collapsible field.
215
+
216
+ Task:
217
+
218
+ We have a `firstName` field, which is collapsible and we need to display a `LanguageLegend`, which would notify user of the language to use.
219
+
220
+ Solution:
221
+
222
+ The simplest configuration with `schema`, `uiSchema` and `formContext` would look something like this
223
+
224
+ ```jsx harmony
225
+ import React from "react";
226
+ import fields from "react-jsonschema-form-extras"
227
+
228
+ let schema = {
229
+ type: "object",
230
+ properties: {
231
+ firstName: { type: "string" }
232
+ }
233
+ }
234
+
235
+ let uiSchema = {
236
+ firstName: {
237
+ "ui:field": "collapsible",
238
+ collapse: {
239
+ field: "StringField",
240
+ legend: {
241
+ component: "LanguageLegend",
242
+ props: {
243
+ language: "EN"
244
+ }
245
+ }
246
+ }
247
+ }
248
+ }
249
+
250
+ let formContext = {
251
+ legends: {
252
+ LanguageLegend: (props) => (<h1>Expected {props.language} characters</h1>)
253
+ }
254
+ }
255
+
256
+ <Form formContext={formContext} schema={schema} uiSchema={uiSchema} fields={fields}>
257
+ ```
258
+
259
+ ## Alternative input fields (`altInput`)
260
+
261
+ ### Purpose
262
+
263
+ You want to enter the same `field` in 2 different ways. For example if a field might be a `string` and `number`
264
+
265
+ ### Use
266
+
267
+ The simplest configuration would look something like this
268
+
269
+ ```json
270
+ {
271
+ "ui:field": "altInput",
272
+ "defInput": "typeahead",
273
+ "altInput": "asyncTypeahead",
274
+ "typeahead": {},
275
+ "asyncTypeahead": {}
276
+ }
277
+ ```
278
+
279
+ In this case user would be able to enter the same field, either by using async typeahead or regular one.
280
+
281
+ ### Properties
282
+
283
+ In order to configure presentation there are few options
284
+
285
+ - `defInput` `string` registry field to use as primary input method
286
+ - `altInput` `string` registry field to use as an alternative input method
287
+ - `altInputSeparator` `string` string to use in between those 2 presentations
288
+
289
+ ## Typeahead, based on [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead) (`typeahead`)
290
+
291
+ ### Purpose
292
+
293
+ This is a wrap of [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead), which allows you to use this project in your `jsonschema-form`
294
+
295
+ ### Use
296
+
297
+ The simplest configuration would be
298
+
299
+ ```json
300
+ {
301
+ "ui:field": "typeahead",
302
+ "typeahead": {
303
+ "options": [{ "state": "New York" }, { "code": "Washington" }],
304
+ "labelKey": "state"
305
+ }
306
+ }
307
+ ```
308
+
309
+ In this case the typeahead would only have 2 options - `New York` and `Washigton`
310
+
311
+ ### Properties
312
+
313
+ All properties that you specify under `typeahead` will be used in the original project.
314
+
315
+ - `focusOnMount` focusOn typeahead, after it was mounted to page
316
+ - `typeahead` all properties that you specify under `typeahead` will be used in the original project.
317
+ Additionally, there are few project specific properties
318
+ - `labelKey` have more flexibility in configuration
319
+ - `labelKey` `string` used a labelKey in [typeahead](https://github.com/ericgio/react-bootstrap-typeahead) project
320
+ - `labelKey` `array` in this case array is a list of fields in original object, which are combined in a single string with a space separator
321
+ - `labelKey` `object` with `fields` `array` of fields to use, `separator` string separator to use between fields
322
+ - `cleanAfterSelection` `boolean` clean selection after component was selected (default false)
323
+ - `mapping` `object` that maps selected object to schema object
324
+
325
+ For complete list of configurations refer to [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead)
326
+
327
+ Here are some use case examples
328
+
329
+ With following options
330
+
331
+ ```json
332
+ [
333
+ {
334
+ "name": "Adventures of Huckleberry Finn",
335
+ "author": "Mark Twain"
336
+ },
337
+ {
338
+ "name": "The Adventures of Tom Sawyer",
339
+ "author": "Mark Twain"
340
+ }
341
+ ]
342
+ ```
343
+
344
+ #### Label key
345
+
346
+ With labelKey `name` there will be 2 options
347
+
348
+ - `Adventures of Huckleberry Finn`
349
+ - `The Adventures of Tom Sawyer`
350
+
351
+ With labelKey `[ "author", "name" ]`, options will be
352
+
353
+ - `Mark Twain Adventures of Huckleberry Finn`
354
+ - `Mark Twain The Adventures of Tom Sawyer`
355
+
356
+ With lableKey `{ fields: [ "author", "name" ], separator: " - " }`, options will be
357
+
358
+ - `Mark Twain - Adventures of Huckleberry Finn`
359
+ - `Mark Twain - The Adventures of Tom Sawyer`
360
+
361
+ #### Mapping
362
+
363
+ Mapping can be one of
364
+
365
+ - not specified, in this case selection is sent to the formData as is
366
+ - `string` which is field name in typeahead selected object
367
+ - `object` with fields corresponding to final schema fields and values, corresponding to fields in typeahead
368
+ - `function` which will be called with typeahead selected objects, which ever value you specify will be used
369
+
370
+ Mapping as undefined (we accept values as is)
371
+
372
+ ```
373
+ {
374
+ "mapping": undefined
375
+ }
376
+ ```
377
+
378
+ would result in
379
+
380
+ - `{ "name": "Adventures of Huckleberry Finn", "author": "Mark Twain" }`
381
+ - `{ "name": "The Adventures of Tom Sawyer", "author": "Mark Twain" }`
382
+
383
+ Mapping as string (we want only name of the book)
384
+
385
+ ```json
386
+ {
387
+ "mapping": "name"
388
+ }
389
+ ```
390
+
391
+ would result in
392
+
393
+ - `"Adventures of Huckleberry Finn"`
394
+ - `"The Adventures of Tom Sawyer"`
395
+
396
+ Mapping as object (we want to change mapping to creator and book)
397
+
398
+ ```json
399
+ {
400
+ "mapping": {
401
+ "creator": "author",
402
+ "book": "name"
403
+ }
404
+ }
405
+ ```
406
+
407
+ would result in
408
+
409
+ - `{ book: "Adventures of Huckleberry Finn", creator: "Mark Twain" }`
410
+ - `{ book: "The Adventures of Tom Sawyer", creator: "Mark Twain" }`
411
+
412
+ Mapping as function (let's say we want to take a first name of the author)
413
+
414
+ ```js
415
+ let uiSchema = {
416
+ mapping: (event) => event.creator.split(" ")[0]
417
+ };
418
+ ```
419
+
420
+ would result in
421
+
422
+ - `"Mark"`
423
+ - `"Mark"`
424
+
425
+ ## Async Typeahead based on [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead) (`asyncTypeahead`)
426
+
427
+ ### Purpose
428
+
429
+ This is a wrap around `async` functionality of [typeahead](https://github.com/ericgio/react-bootstrap-typeahead), supporting some additional defaults.
430
+
431
+ ### Use
432
+
433
+ The simplest configuration would be
434
+
435
+ ```json
436
+ {
437
+ "ui:field": "asyncTypeahead",
438
+ "asyncTypeahead": {
439
+ "url": "https://example.com/state"
440
+ }
441
+ }
442
+ ```
443
+
444
+ This will result in typeahead search with `https://example.com/state?query=${query}`
445
+
446
+ ### Properties
447
+
448
+ Async typeahead extends default configuration list for `typeahead`, by adding few properties under `asyncTypeahead`
449
+
450
+ - `focusOnMount` focusOn typeahead, after it was mounted to page
451
+ - `asyncTypeahead` all properties that you specify under `typeahead` will be used in the original project.
452
+ - `url` search url, that will be used during autocomplete
453
+ - `search` function that will be querying server for data, which takes 2 parameters, and must return a Promise with a json result
454
+ - `url` configured URL
455
+ - `query` typed query string
456
+ - `optionsPath` path to options array in response
457
+ - `labelKey` have more flexibility in configuration
458
+ - `labelKey` `string` used a labelKey in [typeahead](https://github.com/ericgio/react-bootstrap-typeahead) project
459
+ - `labelKey` `array` in this case array is a list of fields in original object, which are combined in a single string with a space separator
460
+ - `labelKey` `object` with `fields` `array` of fields to use, `separator` string separator to use between fields
461
+ - `cleanAfterSelection` `boolean` clean selection after component was selected (default false)
462
+ - `overrideOptions` if true, the user can type any text in the input field (or select an option, then modify it),
463
+ and it will be saved in the RJSF model (default false)
464
+ - `mapping` `object` that maps selected object to schema object
465
+
466
+ For example, let's consider query with `Was` on `url` `https://example.com/state`.
467
+
468
+ By default field will query results with - `https://example.com/state?query=Was`.
469
+
470
+ Let's say we want to override it and query - `https://example.com/state?name=Was&maxSize=1`.
471
+
472
+ Here is how we can do that:
473
+
474
+ ```js
475
+ let uiSchema = {
476
+ "ui:field": "asyncTypeahead",
477
+ asyncTypeahead: {
478
+ url: "https://example.com/state",
479
+ search: (url, query) => fetch(`${url}?name=${query}&maxSize=1`)
480
+ }
481
+ };
482
+ ```
483
+
484
+ That is it.
485
+
486
+ For complete list of async typeahead configurations refer to [react-bootstrap-typeahead](https://github.com/ericgio/react-bootstrap-typeahead)
487
+
488
+ ## RTE, based on [react-rte](https://github.com/sstur/react-rte) (`rte`)
489
+
490
+ ### Purpose
491
+
492
+ This is a simple field, that allows you to enter RTE text inside your string field.
493
+
494
+ ### Use
495
+
496
+ The simplest configuration would be
497
+
498
+ ```json
499
+ {
500
+ "ui:field": "rte",
501
+ "rte": {
502
+ "format": "html"
503
+ }
504
+ }
505
+ ```
506
+
507
+ ### Properties
508
+
509
+ The only property this field requires is `format`
510
+
511
+ - `format` `string` an `rte` output format (default `html`)
512
+ - `updateOnBlur` `boolean` allows for RTE update parent form only after edit finished, to minimize calculations and redraw (default `false`)
513
+
514
+ As with other projects, all configurations, that you'll configure under `uiSchema` `rte` field will be transferred to the actual component.
515
+
516
+ ## Tables, based on [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table) (`table`)
517
+
518
+ ### Purpose
519
+
520
+ This component wraps [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table) for array components, with smart default configurations.
521
+
522
+ ### Use
523
+
524
+ The simplest configuration would be
525
+
526
+ ```json
527
+ {
528
+ "ui:field": "table"
529
+ }
530
+ ```
531
+
532
+ ### Properties
533
+
534
+ You can use `table` field without any predefined configurations, it will generate default table schema with columns.
535
+
536
+ - `tableCols` an array of react-bootstrap-table configurations, that override default generated configurations for the field.
537
+ - `focusOnAdd` column number, when set, adding new row to the table, it will focus on a specified column.
538
+
539
+ By default table component will generate table columns, based on an array schema, with editables, based on field types.
540
+
541
+ You can reuse react-jsonschema-form Components, in table column editing, to do that, you need to define
542
+
543
+ - `field` property in tableCols override section, with `uiSchema` to use for the field.
544
+
545
+ For example let's say we have allergy array, with `allergyName` coming from server source,
546
+ we can enable `asyncTypeahead` on allergyName field in `tableCols` override like this:
547
+
548
+ ```js
549
+ let uiSchema = {
550
+ allergies: {
551
+ classNames: "col-md-12",
552
+ "ui:field": "table",
553
+ table: {
554
+ tableCols: [
555
+ {
556
+ dataField: "allergyName",
557
+ field: "asyncTypeahead",
558
+ uiSchema: {
559
+ "ui:field": "asyncTypeahead",
560
+ asyncTypeahead: {
561
+ bodyContainer: true,
562
+ url: "/allergies/typeahead"
563
+ }
564
+ }
565
+ }
566
+ ]
567
+ }
568
+ }
569
+ };
570
+ ```
571
+
572
+ #### Columns order
573
+
574
+ By default order of columns is defined by `schema` properties field order.
575
+ It might be not always reliable, so there is a way to override it.
576
+ By default the order will follow order of columns in `tableCols` configuration.
577
+
578
+ ```js
579
+ let schema = {
580
+ type: "object",
581
+ properties: {
582
+ medications: {
583
+ type: "array",
584
+ items: {
585
+ type: "object",
586
+ properties: {
587
+ dosage: { type: "number" },
588
+ name: { type: "string" }
589
+ }
590
+ }
591
+ }
592
+ }
593
+ };
594
+
595
+ let uiSchema = {
596
+ medications: {
597
+ "ui:field": "table",
598
+ table: {
599
+ tableCols: [
600
+ {
601
+ dataField: "name"
602
+ },
603
+ {
604
+ dataField: "dosage"
605
+ }
606
+ ]
607
+ }
608
+ }
609
+ };
610
+ ```
611
+
612
+ Here although in medications property schema `dosage` goes before `name`, it will be shown first due to `tableCols` order of columns.
613
+
614
+ #### Cell dataFormat
615
+
616
+ react-bootstrap-table provides custom [dataFormat](https://allenfang.github.io/react-bootstrap-table/docs.html#dataFormat) for rendering data in columns.
617
+ We needed to support serialized configuration, so we extended native functionality, with string configuration,
618
+
619
+ - `object` dataFormat can be a `string` which translates into field name in the object.
620
+ - `date-time` & `date` `string` dataFormat is a format of string presentation, that is generated with moment.js
621
+
622
+ For example, let's say we have an allergies table, with identifier, which consists of some numeric id and string name. When showing to the user, we want to show only name. Here is how we can do this:
623
+
624
+ ```js
625
+ let schema = {
626
+ type: "object",
627
+ properties: {
628
+ allergies: {
629
+ type: "array",
630
+ items: {
631
+ type: "object",
632
+ properties: {
633
+ identified: {
634
+ type: "object",
635
+ properties: {
636
+ id: { type: "string" },
637
+ name: { type: "string" }
638
+ }
639
+ },
640
+ added: { type: "date-time" }
641
+ }
642
+ }
643
+ }
644
+ }
645
+ };
646
+
647
+ let uiSchema = {
648
+ medications: {
649
+ "ui:field": "table",
650
+ table: {
651
+ tableCols: [
652
+ {
653
+ dataField: "identifier",
654
+ dataFormat: "name"
655
+ },
656
+ {
657
+ dataField: "dosage",
658
+ dataFormat: "YYYY-MM-DD"
659
+ }
660
+ ]
661
+ }
662
+ }
663
+ };
664
+ ```
665
+
666
+ In this case dataFormat on identifier field, will translate into selecting name field in identifier object.
667
+
668
+ ### Additional column actions
669
+
670
+ If you need to define additional column actions to the left or to the right of column content you can do that in
671
+ a standard way with `uiSchema` with `leftActions` or `rightActions` defined
672
+
673
+ ```js
674
+ let uiSchema = {
675
+ table: {
676
+ leftActions: [
677
+ {
678
+ action: "delete",
679
+ className: "col-md-1",
680
+ columnClassName: "col-md-1",
681
+ editColumnClassName: "col-md-1",
682
+ icon: "glyphicon glyphicon-minus"
683
+ }
684
+ ],
685
+ rightActions: [
686
+ {
687
+ action: "delete",
688
+ icon: "glyphicon glyphicon-minus",
689
+ text: "Remove"
690
+ }
691
+ ]
692
+ }
693
+ };
694
+ ```
695
+
696
+ Both left and right actions can accept full column configuration, that will be appended to the rendered column,
697
+
698
+ For example, to define delete on each column, you can:
699
+
700
+ ```js
701
+ let uiSchema = {
702
+ table: {
703
+ leftActions: [
704
+ {
705
+ dataField: "delete-button",
706
+ dataFormat: (cell, row, enumObject, rowIndex, formData, onChange) => (
707
+ <span
708
+ onClick={() => onChange(formData.filter((el, i) => rowIndex !== i))}
709
+ >
710
+ "Remove All"
711
+ </span>
712
+ ),
713
+ editable: false,
714
+ displayName: "Left Panel"
715
+ }
716
+ ],
717
+ rightActions: [
718
+ {
719
+ action: "delete",
720
+ icon: "glyphicon glyphicon-minus",
721
+ text: "Delete",
722
+ displayName: "Right Panel"
723
+ }
724
+ ]
725
+ }
726
+ };
727
+ ```
728
+
729
+ In left panel, we have defined delete with a standard `react-bootstrap-table` format, the only difference is dataFormat signature changed,
730
+ appending original formData and onChange callback to relay changes to the listening component.
731
+
732
+ Right panel is defined with small syntactic sugar to simpify action defintion
733
+
734
+ - `action` can be either `delete` string or function, that is equivalent on onClick function with `cell`, `row`, `enumObject`, `rowIndex`, `formData`, `onChange` parameters
735
+ - `icon` icon to use for the column
736
+ - `text` text to use for the column
737
+ - `displayName` column name
738
+
739
+ ## Multi-typeahead field (`multiTypeahead`)
740
+
741
+ ### Purpose
742
+
743
+ This component provides a multi-typeahead dropdown using Material-UI components with multiple selection enabled. It allows users to search and select multiple options, displaying them as chips/tags, and integrates with react-jsonschema-form. Compatible with react-jsonschema-form.
744
+
745
+ ### Recent Changes
746
+
747
+ - **BREAKING CHANGE**: Renamed from `MultiSelectField` to `MultiTypeaheadField`
748
+ - **Field Name**: Changed from `ui:field: "multiSelect"` to `ui:field: "multiTypeahead"`
749
+ - **Configuration**: Changed from `multiSelect: {}` to `multiTypeahead: {}` in uiSchema
750
+ - Uses Material-UI components for multi-typeahead functionality.
751
+ - All styling (border, label, placeholder, chip, dropdown options, icons) is handled via JSS (`withStyles`).
752
+ - Consistent color for label, placeholder, dropdown options, chips, and icons.
753
+ - Placeholder and label are always centered and use color `#003B5CBF`.
754
+ - Chips use background `#00629B` and white text; delete icon is white.
755
+ - Dropdown and clear icons use dark blue (`#00629B`).
756
+ - Input and chip layout is compact, with no extra lines or spacing.
757
+ - Fixed chip grey appearance on click/hover with proper state overrides.
758
+ - Fixed React key prop issues to prevent visual glitches when deleting chips.
759
+
760
+ ### Use
761
+
762
+ The simplest `uiSchema` configuration would be:
763
+
764
+ ```json
765
+ {
766
+ "ui:field": "multiTypeahead",
767
+ "multiTypeahead": {
768
+ "options": [
769
+ { "label": "Option 1", "value": "opt1" },
770
+ { "label": "Option 2", "value": "opt2" }
771
+ ],
772
+ "label": "Choose options",
773
+ "placeholder": "Select..."
774
+ }
775
+ }
776
+ ```
777
+
778
+ ### Properties
779
+
780
+ All properties are configured under the `multiTypeahead` object in uiSchema:
781
+
782
+ - `options` (array): Static list of options to display. Can be an array of objects or strings.
783
+ - `url` (string): URL for API-based options. When provided, options will be fetched dynamically based on user input with 300ms debounce.
784
+ - `search` (function): Custom search function that overrides the default fetch behavior. Takes `(url, query, queryKey)` parameters and must return a Promise.
785
+ - `queryKey` (string): Query parameter key used in API requests (default: "query"). For example, with `queryKey: "search"`, the URL becomes `${url}?search=${query}`.
786
+ - `optionsPath` (string): Path to extract options array from API response. Use dot notation for nested properties (e.g., `"data.results"`, `"response.items"`).
787
+ - `label` (string): Optional label for the field.
788
+ - `placeholder` (string): Optional placeholder text (default: "Select...").
789
+ - `labelTemplate` (string): Template for displaying both option labels in the dropdown and chip labels. Use `{fieldName}` syntax to reference object properties (e.g., `"{name} - {category}"`). **Required for object values** - if not provided, both options and chips will display as empty when dealing with object values. For string values, the string itself will be displayed regardless of template. This template uses the **flattened data structure** created by `valueKeys`.
790
+ - `valueKeys` (array): Array of keys to extract from selected options for the form value (default: `["value"]`). **Note**: When using nested property paths (e.g., `"user.profile.name"`), only the last part of the key chain (`"name"`) will be used as the property name in the resulting value object. The selected data is **flattened** based on these keys before being stored in formData. Both dropdown options and chips use this flattened structure.
791
+
792
+ ### Key Features
793
+
794
+ - **Dual Mode Support**: Works with both static options and dynamic API-based options
795
+ - **Unified Templates**: Use `labelTemplate` to customize how both dropdown options and chips are displayed. Both use the same flattened data structure from `valueKeys`.
796
+ - **Flexible Values**: `valueKeys` allows you to control which properties are saved in the form data and flattens the data structure for consistent display
797
+ - **Nested API Responses**: Use `optionsPath` to extract options from complex API response structures
798
+ - **Custom Query Parameters**: Use `queryKey` to customize the API query parameter name
799
+ - **Search & Filter**: For static options, filters locally; for URL-based options, searches via API
800
+ - **Debounced API Calls**: 300ms debounce prevents excessive API requests during typing
801
+ - **Persistent Selections**: Selected values remain visible even when not in current search results
802
+ - **Clear Functionality**: Clear individual chips or all selections at once
803
+ - **Loading States**: Shows loading indicator during API calls
804
+ - **Keyboard Accessible**: Full keyboard navigation support
805
+ - **Click-away Handling**: Dropdown closes when clicking outside the component
806
+
807
+ ### Example
808
+
809
+ #### Static Options Example
810
+
811
+ ```js
812
+ import Form from "react-jsonschema-form";
813
+ import { MultiTypeaheadField } from "react-jsonschema-form-extras/lib/MultiTypeaheadField";
814
+
815
+ const fields = { multiTypeahead: MultiTypeaheadField };
816
+
817
+ const schema = {
818
+ type: "object",
819
+ properties: {
820
+ fruits: {
821
+ type: "array",
822
+ items: { type: "object" }
823
+ }
824
+ }
825
+ };
826
+
827
+ const uiSchema = {
828
+ fruits: {
829
+ "ui:field": "multiTypeahead",
830
+ multiTypeahead: {
831
+ options: [
832
+ { name: "Apple", category: "Tree Fruit", value: "apple", id: 1 },
833
+ { name: "Banana", category: "Tropical", value: "banana", id: 2 },
834
+ { name: "Cherry", category: "Stone Fruit", value: "cherry", id: 3 }
835
+ ],
836
+ label: "Select Fruits",
837
+ placeholder: "Choose fruits...",
838
+ labelTemplate: "{name} - {category}",
839
+ valueKeys: ["id", "value", "name", "category"]
840
+ }
841
+ }
842
+ };
843
+
844
+ <Form schema={schema} uiSchema={uiSchema} fields={fields} />;
845
+ ```
846
+
847
+ #### Dynamic/API-based Options Example
848
+
849
+ ```js
850
+ const uiSchema = {
851
+ medications: {
852
+ "ui:field": "multiTypeahead",
853
+ multiTypeahead: {
854
+ url: "/api/medications/search",
855
+ queryKey: "search", // Use "search" instead of default "query"
856
+ optionsPath: "data.medications", // Extract from nested response
857
+ label: "Select Medications",
858
+ placeholder: "Type to search medications...",
859
+ labelTemplate: "{name} ({strength})",
860
+ valueKeys: ["id", "name", "strength"],
861
+ // Optional custom search function
862
+ search: (url, query, queryKey) => {
863
+ return fetch(
864
+ `${url}?${queryKey}=${encodeURIComponent(query)}&limit=20`
865
+ ).then((res) => res.json());
866
+ // No need to extract data.results here, optionsPath will handle it
867
+ }
868
+ }
869
+ }
870
+ };
871
+
872
+ // Without queryKey specified (defaults to "query") but with optionsPath
873
+ const uiSchemaWithOptionsPath = {
874
+ users: {
875
+ "ui:field": "multiTypeahead",
876
+ multiTypeahead: {
877
+ url: "/api/users/search", // Will call: /api/users/search?query=userInput
878
+ optionsPath: "response.users", // Extract from { response: { users: [...] } }
879
+ labelTemplate: "{firstName} {lastName}",
880
+ valueKeys: ["id", "username", "firstName", "lastName"]
881
+ }
882
+ }
883
+ };
884
+
885
+ // Simple case - API returns array directly (no optionsPath needed)
886
+ const uiSchemaDefault = {
887
+ tags: {
888
+ "ui:field": "multiTypeahead",
889
+ multiTypeahead: {
890
+ url: "/api/tags/search", // API returns: [{ name: "tag1" }, { name: "tag2" }]
891
+ labelTemplate: "{name}",
892
+ valueKeys: ["id", "name"]
893
+ }
894
+ }
895
+ };
896
+ ```
897
+
898
+ #### Simple String Array Example
899
+
900
+ ```js
901
+ const schema = {
902
+ type: "object",
903
+ properties: {
904
+ tags: {
905
+ type: "array",
906
+ items: { type: "string" }
907
+ }
908
+ }
909
+ };
910
+
911
+ const uiSchema = {
912
+ tags: {
913
+ "ui:field": "multiTypeahead",
914
+ multiTypeahead: {
915
+ options: ["JavaScript", "React", "Node.js", "Python", "Java"],
916
+ label: "Programming Languages",
917
+ placeholder: "Select languages..."
918
+ }
919
+ }
920
+ };
921
+ ```
922
+
923
+ #### ValueKeys with Nested Properties Example
924
+
925
+ ```js
926
+ // Options with nested properties (original structure)
927
+ const options = [
928
+ {
929
+ user: { profile: { name: "John Doe" }, id: 123 },
930
+ department: { info: { title: "Engineering" } },
931
+ role: "Developer"
932
+ }
933
+ ];
934
+
935
+ const uiSchema = {
936
+ employees: {
937
+ "ui:field": "multiTypeahead",
938
+ multiTypeahead: {
939
+ options: options,
940
+ // labelTemplate uses FLATTENED data structure (after valueKeys processing)
941
+ // Both dropdown options and chips use the same flattened structure
942
+ labelTemplate: "{name} - {role}",
943
+ valueKeys: [
944
+ "user.profile.name",
945
+ "user.id",
946
+ "department.info.title",
947
+ "role"
948
+ ]
949
+ }
950
+ }
951
+ };
952
+
953
+ // How it works:
954
+ // 1. Options are transformed once using valueKeys to create flattened structure:
955
+ // {
956
+ // name: "John Doe", // from user.profile.name (uses last part: "name")
957
+ // id: 123, // from user.id (uses last part: "id")
958
+ // title: "Engineering", // from department.info.title (uses last part: "title")
959
+ // role: "Developer" // from role (uses last part: "role")
960
+ // }
961
+ // 2. Both dropdown and chips show: "John Doe - Developer" (using labelTemplate with flattened structure)
962
+ // 3. FormData contains the same flattened structure as displayed
963
+ ```
964
+
965
+ ### Custom Styling
966
+
967
+ All styles are handled via JSS (`withStyles`) in the component. The styling is designed to be consistent and follows Material-UI design patterns with custom color overrides:
968
+
969
+ **Input Field:**
970
+
971
+ - Border color: `#DFE6EB`
972
+ - Font family: Mulish
973
+ - Input text color: `#003B5C`
974
+ - Label/placeholder color: `#003B5CBF`
975
+ - Minimum height: 56px with centered alignment
976
+
977
+ **Chips (Selected Items):**
978
+
979
+ - Background: `#00629B` (blue)
980
+ - Text color: White
981
+ - Delete icon: White
982
+ - Font: Mulish, 12px
983
+ - Proper state handling for hover/focus/active states
984
+
985
+ **Dropdown:**
986
+
987
+ - Background: White
988
+ - Border: `#DFE6EB`
989
+ - Border radius: 4px (bottom only)
990
+ - Box shadow: `0 2px 8px rgba(0,0,0,0.1)`
991
+ - Max height: 200px with scroll
992
+ - Option hover: `#f5f5f5`
993
+
994
+ **Icons:**
995
+
996
+ - Dropdown indicator: `#00629B`
997
+ - Clear button: `#00629B`
998
+ - Loading indicator: Displays during API calls
999
+
1000
+ **Layout:**
1001
+
1002
+ - Chips and input field are properly aligned in a flex container
1003
+ - Input field takes remaining space with minimum 120px width
1004
+ - Clear button appears when selections exist
1005
+ - Compact layout with optimized spacing
1006
+
1007
+ To customize styling, edit the `styles` object in `MultiTypeaheadField.js` using JSS syntax.
1008
+
1009
+ ## React Day Picker, based on [react-day-picker](https://github.com/gpbl/react-day-picker) (`rdp`)
1010
+
1011
+ ### Purpose
1012
+
1013
+ Allows you to use react-day-picker as input `ui:field`. This component works only with `string` formatted as `date` and `date-time`.
1014
+
1015
+ ### Use
1016
+
1017
+ The simplest configuration would be
1018
+
1019
+ ```json
1020
+ {
1021
+ "ui:field": "rdp"
1022
+ }
1023
+ ```
1024
+
1025
+ ### Properties
1026
+
1027
+ All configurations, that you'll configure under `uiSchema` `rdp` field will be transferred to the actual component.
1028
+
1029
+ For example to enable `Today` button, you would need to specify following uiSchema
1030
+
1031
+ ```json
1032
+ {
1033
+ "ui:field": "rdp",
1034
+ "rdp": {
1035
+ "dayPickerProps": {
1036
+ "todayButton": "Today"
1037
+ }
1038
+ }
1039
+ }
1040
+ ```
1041
+
1042
+ For the full list of properties refer to [React Day Picker](http://react-day-picker.js.org).
1043
+
1044
+ ## Table Expandable Row Component
1045
+
1046
+ ### Purpose
1047
+
1048
+ to enable expandable row in table component
1049
+
1050
+ ### Use
1051
+
1052
+ to expand table rows
1053
+
1054
+ ```json
1055
+ {
1056
+ "table": {
1057
+ "isTableExpandable": false,
1058
+ "allowOneRowExpanding": true
1059
+ }
1060
+ }
1061
+ ```
1062
+
1063
+ ### Properties
1064
+
1065
+ All configurations, that you'll configure under `uiSchema` `table` field will be transferred to the actual component.
1066
+
1067
+ For example to enable `ExpandRow` button, you would need to specify following uiSchema
1068
+
1069
+ ```json
1070
+ {
1071
+ "table": {
1072
+ "isTableExpandable": false,
1073
+ "allowOneRowExpanding": true
1074
+ }
1075
+ }
1076
+ ```
1077
+
1078
+ ## Contribute
1079
+
1080
+ - Issue Tracker: github.com/RxNT/react-jsonschema-extras/issues
1081
+ - Source Code: github.com/RxNT/react-jsonschema-extras
1082
+
1083
+ ## Support
1084
+
1085
+ If you are having issues, please let us know here or on StackOverflow.
1086
+
1087
+ ## License
1088
+
1089
+ The project is licensed under the Apache Licence 2.0.