Refreshing your modal or settings tab in Obsidian

When I build a custom modal or settings tab in Obsidian plugin development, I use a quick hack for refreshing it when settings are changed that I thought I’d share it here.

In this example, I’ve used a PluginSettingsTab, but it can also be applied to a Modal.

Bluesky
Threads
Twitter / X
Mastodon
Instagram

The code for your settings tab might look like the below code. In it, I’ve created a function called registerSettingsTab which I call from my main file on plugin load. It then registers the settings tab defined below.

Note that the settings tab has two toggle components being added to the tab using Obsidian’s API.

export function registerSettingsTab(plugin: Plugin) {
    plugin.addSettingTab(new MySettingsTab(plugin.app, plugin));
}

export class MySettingsTab extends PluginSettingTab {
    plugin: MyPlugin;

    constructor(app: App, plugin: MyPlugin) {
        super(app, plugin);
        this.plugin = plugin;
    }

    display(): void {
        const {containerEl} = this;
        containerEl.empty();


        new Setting(containerEl)
            .setName('Enable second toggle')
            .addToggle((toggle) => {
                toggle.setValue(plugin.settings.firstToggle);
                toggle.onChange(async (value) => {
                    plugin.settings.firstToggle = value;
                    await plugin.saveSettings();
                });
            });


        if(plugin.settings.firstToggle) {

            new Setting(containerEl)
                .setName('Second toggle')
                .addToggle((toggle) => {
                    // ... do stuff
                });

        }

    }
}

Note: Obsidian also promotes letting it’s API lay out your settings automatically. If that’s the approach you’re going with, your code will look different to above — And this article won’t be relevant to you.

Updating the first toggle

In the first toggle, you’ll see that when the settings tab is opened, it’s initial value is set to the boolean stored in plugin.settings.firstToggle.

After the user clicks the toggle, the Obsidian component updates itself visibly, and then calls the onChange handler I’ve given it. This then updates the relevant boolean in the plugin’s settings to match and saves the settings.

So far, this is pretty straight forward.

Updating the second toggle

The second toggle can be set up as straight forwardly as the first (So I’ve not put in its code), except that I only want the second toggle to be visible if the first toggle is set to true.

When the tab loads, this works fine. The If statement that checks plugin.settings.firstToggle runs or skips the code to show or hide the second toggle.

The problem arises, however, when the first toggle is changed while the tab is already open. This isn’t a React file, so we can’t set up a state that auto refreshes the relevant areas. That If statement will never get run again.

A basic solution

One solution is to create an empty variable to hold a reference to the second toggle when it’s created. ie.

// At head of class
secondToggle: Setting;

// When creating second toggle
this.secondToggle = new Settings(...etc.

Now the first Toggle can reference the second toggle and hide it. However, this adds more boilerplate than I like, because the secondToggle variable might not be assigned, so you have to handle a null case. And if you have lots of dependant settings within your tab, it starts to get convoluted.

A quick hack solution

A quick hack solution that I’ve used in the past can make this easier, but it has drawbacks.

We know that when the display function runs initially, everything is displayed correctly according to the settings at that time. Therefore, an easy way around this is to simply run that display function again after updating the settings.

    toggle.onChange(async (value) => {
        plugin.settings.firstToggle = value;
        await plugin.saveSettings();
    });

In order for this to work, make sure you empty the DOM container at the start of the display function. It may not be necessary on it’s first run, but it will be on subsequent runs.

containerEl.empty();

Lastly, there are big drawbacks to this method. When the tab is rebuilt using the display method, the DOM container shrinks to zero height when it’s cleared and is then populated again.

The user won’t notice this happen, however if the tab is longer than the screen it will be scrolled to the top — Which is a horrendous user experience and quite disorienting.

It also completely breaks keyboard accessibility because it moves the keyboard focus back to the top as well.

So, in short, you can use this.display() to refresh the settings tab, but only so long as your settings tab is very short and you’re still in development.

It’s a good way to start quickly while you’re figuring out the settings layout, but you’ll need to adjust it before publishing to maintain the right level of user experience.

Thanks…

I also dissect and speculate on design and development.
Digging into subtle details and implications, and exploring broad perspectives and potential paradigm shifts.
Check out my conceptual articles on Substack or find my latest below.


You can also find me on Threads, Bluesky, Mastodon, or xTwitter for more diverse posts about ongoing projects.

My latest articles

Staging XR scenes (Keep doing your crappy little drawings)

Some people create beautiful perspective illustrations to visualise and storyboard their virtual reality designs And it’s tempting to think you’re not a strong designer if you’re not doing that too…

Focal point blocking for XR media

Planning out a linear VR experience requires thinking about where the viewers attention might be. Thinking about the focal points…

Designing immersive experiences

In traditional cinema, TV, or even the more modern phone screen, there’s limited screen real-estate. But removing that limitation creates a design problem…

The future is not prompt engineered

Let’s not pretend the importance of prompt engineering is ubiquitous. The most prevalent power of generative AI is in the way it adapts to us, not the other way around…

The typography of dates, times, & filenames

A deep dive into carefully considered date formatting, line length and general typography attributes of filenames…

Loosening the Shackles of Rapid Authoring Tools

Rapid authoring tools like Articulate Storyline and Evolve Authoring make sharing projects possible across a team of non-programmers, but your design must often adapted to the limited range of possibilities the tool allows…
Bluesky
Threads
Twitter / X
Mastodon
Instagram


Author:

Date:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.