buildSelectOrInput: load default only when page is constructed
This commit is contained in:
parent
8e5576db94
commit
e94a7b1058
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,6 @@
|
|||
import type Mithril from 'mithril';
|
||||
import type Stream from 'mithril/stream';
|
||||
import app from 'flarum/admin/app';
|
||||
import AdminPage, { CommonSettingsItemOptions } from 'flarum/admin/components/AdminPage';
|
||||
import SelectOrInput from "../../common/Components/SelectOrInput";
|
||||
import generateElementId from 'flarum/admin/utils/generateElementId';
|
||||
|
|
@ -14,7 +16,9 @@ export interface SelectOrInputSettingComponentOptions extends SelectOrInputSetti
|
|||
type: 'select-or-input';
|
||||
}
|
||||
|
||||
var firstLoadCompletedSet: Set<string> = new Set();
|
||||
interface StreamWithMark<T> extends Stream<T> {
|
||||
mark?: true;
|
||||
}
|
||||
|
||||
export default function (this: AdminPage, _entry: CommonSettingsItemOptions) {
|
||||
// do this cast because function signature is restricted
|
||||
|
|
@ -22,25 +26,38 @@ export default function (this: AdminPage, _entry: CommonSettingsItemOptions) {
|
|||
const [inputId, helpTextId] = [generateElementId(), generateElementId()];
|
||||
const { setting, help, label, ...componentAttrs } = entry;
|
||||
const { default: defaultValue, options, checkboxDescription, ...otherAttrs } = componentAttrs;
|
||||
const value = this.setting(setting)();
|
||||
|
||||
let settingElement: Mithril.Children;
|
||||
|
||||
const firstLoadCompleted = firstLoadCompletedSet.has(entry.setting);
|
||||
// Trick: add a marker property to the AdminPage's setting stream,
|
||||
// which contructs and destructs with AdminPage so that default is
|
||||
// only loaded when the page is created.
|
||||
// Default should only be loaded once in a page because when checkbox
|
||||
// is checked, SelectOrInput will set its value to empty string so that
|
||||
// it becomes an empty input. If default is loaded every time when value
|
||||
// is falsy, SelectOrInput will not work properly.
|
||||
const settingStream = this.settings[setting] as StreamWithMark<string>;
|
||||
let value = settingStream();
|
||||
if (!settingStream.mark) {
|
||||
settingStream.mark = true;
|
||||
if (!value) {
|
||||
app.data.settings[setting] = defaultValue;
|
||||
settingStream(defaultValue);
|
||||
value = settingStream();
|
||||
}
|
||||
}
|
||||
|
||||
settingElement = (
|
||||
<SelectOrInput
|
||||
id={inputId}
|
||||
aria-describedby={helpTextId}
|
||||
value={(!firstLoadCompleted && !value) ? defaultValue : value}
|
||||
value={value}
|
||||
options={options}
|
||||
onchange={this.settings[setting]}
|
||||
onchange={settingStream}
|
||||
checkboxDescription={checkboxDescription}
|
||||
{...otherAttrs}
|
||||
/>
|
||||
);
|
||||
|
||||
if (!firstLoadCompleted) firstLoadCompletedSet.add(entry.setting);
|
||||
|
||||
return (
|
||||
<div className="Form-group">
|
||||
{label && <label for={inputId}>{label}</label>}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ export interface ISelectOrInputAttrs<
|
|||
rawTextInputAttrs?: ComponentAttrs;
|
||||
}
|
||||
|
||||
// when value is `undefined`, choose the first item of select
|
||||
// when value is in select, use value as value of select
|
||||
// otherwise, use value as value of input
|
||||
export default class SelectOrInput<CustomAttrs extends ISelectOrInputAttrs> extends Component<CustomAttrs> {
|
||||
private onCheckboxChange(checked: boolean, component: Checkbox) {
|
||||
this.attrs.value = checked ? '' : undefined;
|
||||
|
|
|
|||
Loading…
Reference in New Issue