Skip to content

Commit d89a8e3

Browse files
committed
Finalize handling of defaults in checklists and dropdowns
1 parent 262b0dc commit d89a8e3

File tree

6 files changed

+58
-3
lines changed

6 files changed

+58
-3
lines changed

data/EXAMPLE/config.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,22 @@ form:
113113
type: dropdown
114114
label: 'Dropdown'
115115
empty_label: 'Please choose'
116+
default: 'Default choice'
116117
choices:
117118
- 'Choice #1'
118119
- 'Choice #2'
120+
- 'Default choice'
119121
- 'Choice #3'
122+
dropdownMulti:
123+
type: dropdown
124+
multiselect: true
125+
label: 'Multi Dropdown'
126+
default: 'Default choice in multi'
127+
choices:
128+
- 'Choice #1 in multi'
129+
- 'Choice #2 in multi'
130+
- 'Default choice in multi'
131+
- 'Choice #3 in multi'
120132
checklist1:
121133
type: checklist
122134
alignment: vertical

doc/formelements.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,10 @@ Representation of a select input.
355355
Options:
356356
* **EITHER** `choices` _(optionally required)_ - defines available options. Markdown is supported.
357357
* **OR** `conditional_choices` _(optionally required)_ - defines options available if a condition is met (depending on the value of another form field). This option has priority over `choices`!
358-
* `empty_label` _(optional)_ - a placeholder text shown if no value was chosen (e.g. "Please select"). **Note:** this is not a real option and has no value that could be saved.
358+
* `empty_label` _(optional)_ - a placeholder text shown if no value has been chosen (e.g. "Please select"). **Note:** this is not a real option and has no value that could be saved. In multiselect fields it is irrelevant and ignored.
359359
* `multiselect` _(optional)_ - enables selecting multiple options
360360
* `size` _(optional)_ - if multiselect is turned on this defines the number of rows shown, otherwise ignored
361-
* `default` _(optional)_ : Preselects a choice. This is only triggered if the form was never saved before. **Preselect in toggles are not supported yet.**
361+
* `default` _(optional)_ : Preselects a choice. This is only applied if the form has never been saved before. **Preselect in toggles are not supported.**
362362

363363
```yaml
364364
<id>:
@@ -395,7 +395,7 @@ Representation of a checkbox group.
395395
Options:
396396
* `alignment` _(optional)_ - sets the alignment of the checkboxes, possible values are `vertical` or `horizontal` (default)
397397
* `choices` _(required)_ - defines available options/checkboxes. Markdown is supported.
398-
* `default` _(optional)_ : Preselects a choice. This is just triggered if the form was never saved before. **Preselect in toggles are not supported yet.**
398+
* `default` _(optional)_ : Preselects a choice. This is only applied if the form has never been saved before. **Preselect in toggles are not supported.**
399399
```yaml
400400
<id>:
401401
type: checklist

js_src/State.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ export class State {
2020
/** @type {Proxy<object>} Values previously set, before a component was removed */
2121
oldValues;
2222

23+
/** @type {boolean} Relevant when populating default values */
24+
hasInitialValues;
25+
2326
constructor(initialValues = {}) {
27+
this.hasInitialValues = !!Object.keys(initialValues).length;
2428
this.values = this.#createProxy(initialValues, State.STATE_VALUE_CHANGE_EVENT);
2529
this.oldValues = this.#createProxy();
2630
}

js_src/components/ChecklistComponent.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ export class ChecklistComponent extends BaseComponent {
7070
this.myState.value = state;
7171
}
7272

73+
/**
74+
* Ensure Set type and apply defaults, but only on initial rendering,
75+
* when the form has no values yet.
76+
*
77+
* @param {State} state
78+
* @param {Object} config
79+
* @returns {ComponentState}
80+
*/
7381
stateHook(state, config) {
7482
let myState = new ComponentState(state, config.name);
7583
myState.value = U.stateMultivalue(myState.value);

js_src/components/DropdownComponent.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {BaseComponent} from './BaseComponent.js';
22
import {U} from '../U.js';
3+
import {ComponentState} from "../ComponentState";
34

45
export class DropdownComponent extends BaseComponent {
56

@@ -126,6 +127,32 @@ export class DropdownComponent extends BaseComponent {
126127
return super.shouldUpdate(detail) || optionsShouldUpdate();
127128
}
128129

130+
/**
131+
* Ensure Set type for multiselect values.
132+
* Apply defaults, but only on initial rendering, when the form has no values yet.
133+
*
134+
* @param {State} state
135+
* @param {Object} config
136+
* @returns {ComponentState}
137+
*/
138+
stateHook(state, config) {
139+
let myState = new ComponentState(state, config.name);
140+
141+
if (!state.hasInitialValues && !myState.value && "default" in config) {
142+
myState.value = config.default;
143+
}
144+
145+
if (config.multiselect) {
146+
myState.value = U.stateMultivalue(myState.value);
147+
148+
if (!state.hasInitialValues && !myState.value.size && "default" in config) {
149+
myState.value.add(config.default);
150+
}
151+
}
152+
153+
return myState;
154+
}
155+
129156
/**
130157
* Clear state when options change to remove potentially invalid choices
131158
*

src/FormGenerator/Form.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ public function __construct(string $formId)
5252

5353
try {
5454
$this->values = YamlHelper::parseYaml($this->getFormDirectory() . 'values.yaml');
55+
// an empty array must be converted into an object
56+
if (empty($this->values)) {
57+
throw new \Exception("File is present but empty, this will result in invalid type of 'values' in JSON");
58+
}
5559
} catch (\Exception $exception) {
5660
// no stored values.yaml, an empty object in JSON
5761
$this->values = new \stdClass();

0 commit comments

Comments
 (0)