Custom CSS classes persist on reused Setting rows after dynamic settings update

Hi, I found a possible issue with the declarative settings API introduced in Obsidian 1.13.

When using PluginSettingTab.getSettingDefinitions() with a dynamic SettingDefinitionGroup, custom CSS classes assigned in a render callback may persist when Obsidian reuses a Setting row after the definitions are rebuilt.

Minimal reproduction:

  1. Create a dynamic group with a list of custom rows.

  2. In each list row, assign a custom class inside render:

render: (setting) => {

    setting.setClass("custom-list-row");
    // Render the row contents
}
  1. Add a new item to the list and call:
this.update();
  1. Delete the newly added item and call this.update() again.

In my case, the separate “Add item” row was reused from a previous list row. It retained the previous row’s classes, such as:

custom-list-row mod-toggle

This caused the Add button row to inherit the list-row CSS layout and changed its appearance/alignment.

The issue seems to be that the framework reuses the existing Setting DOM element, but does not remove custom classes assigned by a previous render callback before rendering the element again.

As a workaround, I currently remove the possible stale classes explicitly in the Add button row’s render callback:

render: (setting) => {
    setting.settingEl.removeClass(
        "custom-list-row",
        "custom-other-row",
        "mod-toggle",
    );

    setting.addButton((button) => {
        // ...
    });
}

Could the declarative settings renderer either:

  • clear custom classes from a reused Setting row before invoking render, or
  • provide a documented cleanup/reset mechanism for classes added through setting.setClass()?

This was observed with getSettingDefinitions(), dynamic groups, render callbacks, and this.update() after adding/removing items.

Recording

(video not allowed, so I transform it to a gif)

01018f36-50c1-4c7f-9e0b-3d14f82b1cdc

1 Like