What's the TJS way to extend FormApplication?

Specifically I want a custom type to register a component via game.settings.register e.g. a multi-select or checkbox list. E.g. I currently have this:
game.settings.registerMenu(MODULE_ID, SettingKeys.SOURCES, {
name: 'compendiums'),
label: 'Compendiums'),
icon: 'fas fa-atlas',
type: CompendiumSourcesSubmenu,
restricted: true,
});
game.settings.registerMenu(MODULE_ID, SettingKeys.SOURCES, {
name: 'compendiums'),
label: 'Compendiums'),
icon: 'fas fa-atlas',
type: CompendiumSourcesSubmenu,
restricted: true,
});
But I would like that CompendiumSourcesSubmenu to be a svelte component, rather than the TypeScript / Handlebars extension to FormApplication that it currently is (as it has been ported from an existing module)
2 Replies
TyphonJS (Michael)
It's highly recommended to use the "dummy FormApplication" route to register an app / menu setting. You create a fake FormApplication and launch a normal SvelteApplication instead from this fake FormApplication. You can also make this fake FormApplication be a static way to launch the settings config from elsewhere. You can see this in the unreleased mce-everywhere package: The fake FormApplication: https://github.com/typhonjs-fvtt/mce-everywhere/blob/main/src/view/ConfigSettingButton.js Registering a hook to open the Svelte settings app and registering a menu: https://github.com/typhonjs-fvtt/mce-everywhere/blob/main/src/model/mceGameSettings.js#L49-L62 ---- However, a better solution that likely is available on a recent v11 / v12? install is if a function can be directly registered. The fake FormApplication approach is how you do it before a version of Foundry that can accept a function for the settings menu registration. I haven't followed up when / if function registration may have been implemented in core. I know it was put in as a feature request 1-2 years ago, so might be the best way to do things now.
geoidesic
geoidesic3mo ago
The answer from Foundry was:
register(namespace, key, data) {
//...
// Validate type
if ( data.type ) {
const allowedTypes = [foundry.data.fields.DataField, foundry.abstract.DataModel, Function];
if ( !allowedTypes.some(t => data.type instanceof t) ) {
throw new Error(`Setting ${key} type must be a DataField, DataModel, or callable function`);
}
register(namespace, key, data) {
//...
// Validate type
if ( data.type ) {
const allowedTypes = [foundry.data.fields.DataField, foundry.abstract.DataModel, Function];
if ( !allowedTypes.some(t => data.type instanceof t) ) {
throw new Error(`Setting ${key} type must be a DataField, DataModel, or callable function`);
}
from v12's client/core/settings.js the built-in type functions are functions and weren't whitelisted in v11 or anything, so it should take an arbitrary function just as well Does that qualify? Also, looking at mce-everywhere. I saw this:
// Get a store that is synchronized with session storage.
const stateStore = application.reactive.sessionStorage.getStore(sessionConstants.appState);
// Get a store that is synchronized with session storage.
const stateStore = application.reactive.sessionStorage.getStore(sessionConstants.appState);
What's that all about? I haven't encountered this before. I tried the dymmy FormApplication way, and I can register and display the settings, but I don't know how to save them? Looks like it saves automatically. Which might be weird for users who are used to having to save settings. But I think I prefer it. However any registered onChange handler for the setting won't run if the save isn't triggered. So it might be useful to be able to trigger the save?
Want results from more Discord servers?
Add your server