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 Mithril from 'mithril';
|
||||||
|
import type Stream from 'mithril/stream';
|
||||||
|
import app from 'flarum/admin/app';
|
||||||
import AdminPage, { CommonSettingsItemOptions } from 'flarum/admin/components/AdminPage';
|
import AdminPage, { CommonSettingsItemOptions } from 'flarum/admin/components/AdminPage';
|
||||||
import SelectOrInput from "../../common/Components/SelectOrInput";
|
import SelectOrInput from "../../common/Components/SelectOrInput";
|
||||||
import generateElementId from 'flarum/admin/utils/generateElementId';
|
import generateElementId from 'flarum/admin/utils/generateElementId';
|
||||||
|
|
@ -14,7 +16,9 @@ export interface SelectOrInputSettingComponentOptions extends SelectOrInputSetti
|
||||||
type: 'select-or-input';
|
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) {
|
export default function (this: AdminPage, _entry: CommonSettingsItemOptions) {
|
||||||
// do this cast because function signature is restricted
|
// 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 [inputId, helpTextId] = [generateElementId(), generateElementId()];
|
||||||
const { setting, help, label, ...componentAttrs } = entry;
|
const { setting, help, label, ...componentAttrs } = entry;
|
||||||
const { default: defaultValue, options, checkboxDescription, ...otherAttrs } = componentAttrs;
|
const { default: defaultValue, options, checkboxDescription, ...otherAttrs } = componentAttrs;
|
||||||
const value = this.setting(setting)();
|
|
||||||
let settingElement: Mithril.Children;
|
let settingElement: Mithril.Children;
|
||||||
|
// Trick: add a marker property to the AdminPage's setting stream,
|
||||||
const firstLoadCompleted = firstLoadCompletedSet.has(entry.setting);
|
// 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 = (
|
settingElement = (
|
||||||
<SelectOrInput
|
<SelectOrInput
|
||||||
id={inputId}
|
id={inputId}
|
||||||
aria-describedby={helpTextId}
|
aria-describedby={helpTextId}
|
||||||
value={(!firstLoadCompleted && !value) ? defaultValue : value}
|
value={value}
|
||||||
options={options}
|
options={options}
|
||||||
onchange={this.settings[setting]}
|
onchange={settingStream}
|
||||||
checkboxDescription={checkboxDescription}
|
checkboxDescription={checkboxDescription}
|
||||||
{...otherAttrs}
|
{...otherAttrs}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!firstLoadCompleted) firstLoadCompletedSet.add(entry.setting);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="Form-group">
|
<div className="Form-group">
|
||||||
{label && <label for={inputId}>{label}</label>}
|
{label && <label for={inputId}>{label}</label>}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,9 @@ export interface ISelectOrInputAttrs<
|
||||||
rawTextInputAttrs?: ComponentAttrs;
|
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> {
|
export default class SelectOrInput<CustomAttrs extends ISelectOrInputAttrs> extends Component<CustomAttrs> {
|
||||||
private onCheckboxChange(checked: boolean, component: Checkbox) {
|
private onCheckboxChange(checked: boolean, component: Checkbox) {
|
||||||
this.attrs.value = checked ? '' : undefined;
|
this.attrs.value = checked ? '' : undefined;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue