Skip to content

fix(Switch widget): sync isSwitchedOn meta on programmatic changes#41749

Open
itsmejay80 wants to merge 2 commits intoappsmithorg:releasefrom
itsmejay80:fix/switch-widget-stale-isswitchedon
Open

fix(Switch widget): sync isSwitchedOn meta on programmatic changes#41749
itsmejay80 wants to merge 2 commits intoappsmithorg:releasefrom
itsmejay80:fix/switch-widget-stale-isswitchedon

Conversation

@itsmejay80
Copy link
Copy Markdown

@itsmejay80 itsmejay80 commented Apr 18, 2026

Description

Fixes a stale-binding bug in the Switch widget. Once a user interacts with the widget at least once, its isSwitchedOn meta takes precedence over the derived defaultSwitchState. Any subsequent programmatic change to defaultSwitchState (via Switch1.setValue(...), a bound default state expression, or a ToggleButton driving the switch) updated defaultSwitchState but left the stale meta in place. Widgets bound to Switch1.isSwitchedOn kept reading the old value.

This PR adds a small componentDidUpdate block in SwitchWidget that syncs the meta value whenever isSwitchedOn changes, mirroring the existing behavior in CheckboxWidget.componentDidUpdate (app/client/src/widgets/CheckboxWidget/widget/index.tsx).

Fixes #41566

Automation

/ok-to-test tags="@tag.Switch, @tag.Binding"

🔍 Cypress test results

Caution

If you modify the content in this section, you are likely to disrupt the CI result for your PR.

Testing

Manual repro from the issue:

  1. Drop a Switch, a ToggleButton, and a Button on the canvas.
  2. Bind Button.disabled to {{Switch1.isSwitchedOn}}.
  3. Wire ToggleButton.onChange to {{Switch1.setValue(!Switch1.isSwitchedOn)}}.
  4. Toggle the Switch once directly, then toggle via ToggleButton — before the fix, Button.disabled goes stale; after the fix it follows the switch consistently.

Communication

Should the DevRel and Marketing teams inform users about this change?

  • Yes
  • No

Summary by CodeRabbit

  • Bug Fixes
    • Switch widget now correctly syncs its on/off state when changed programmatically, ensuring dependent widgets reflect the current state.
  • Tests
    • Added a regression test to verify programmatic toggles update dependent bindings and prevent test interference.

…hanges

Mirrors the existing CheckboxWidget behavior so external updates to
defaultSwitchState (setValue, bound expressions) propagate to the
isSwitchedOn meta property. Without this, bindings reading
Switch.isSwitchedOn kept returning the stale meta value once the user
had toggled the switch at least once.

Fixes appsmithorg#41566

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 18, 2026 22:58
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a1679faf-7d2e-476e-b581-7d7abd589a62

📥 Commits

Reviewing files that changed from the base of the PR and between c2788cb and 7f655f5.

📒 Files selected for processing (2)
  • app/client/cypress/e2e/Regression/ClientSide/Widgets/Switch/Switch_spec.js
  • app/client/src/widgets/SwitchWidget/widget/index.tsx
✅ Files skipped from review due to trivial changes (1)
  • app/client/cypress/e2e/Regression/ClientSide/Widgets/Switch/Switch_spec.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/client/src/widgets/SwitchWidget/widget/index.tsx

Walkthrough

Updated the Switch widget to detect external isSwitchedOn prop changes and synchronize that value to widget meta; added a Cypress regression test that verifies programmatic and UI-driven toggles update the bound text widget correctly.

Changes

Cohort / File(s) Summary
Switch widget update
app/client/src/widgets/SwitchWidget/widget/index.tsx
Added componentDidUpdate check for changes to isSwitchedOn and calls updateWidgetMetaProperty("isSwitchedOn", ...) to keep widget meta synchronized with externally driven prop updates.
Regression test
app/client/cypress/e2e/Regression/ClientSide/Widgets/Switch/Switch_spec.js
Added a new regression test that binds a Text widget to Toggler.isSwitchedOn, verifies initial programmatic defaultstate, toggles via UI and property pane, and asserts dependent updates; restores original binding at end.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

A tiny switch once lost its song,
Now hears the props and sings along.
Tests confirm the dance and beat,
Meta and state again compete—complete. ⚡🔁

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: syncing isSwitchedOn meta on programmatic changes to the Switch widget.
Description check ✅ Passed The description includes the issue reference, clear problem statement, solution approach, manual testing steps, and automation tags as per template requirements.
Linked Issues check ✅ Passed The PR directly addresses the root cause of issue #41566 by syncing isSwitchedOn meta on programmatic changes, and includes a regression test validating the fix.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the stale-binding bug in the Switch widget and validating it with a regression test.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/client/src/widgets/SwitchWidget/widget/index.tsx`:
- Around line 437-440: The stale-meta synchronization is incorrectly gated by
the presence of an action handler; remove the onChange guard so meta updates run
whenever isSwitchedOn changes. In the componentDidUpdate (or the method
containing the if block) replace the condition that checks both
this.props.isSwitchedOn !== prevProps.isSwitchedOn && this.props.onChange with a
check that only compares this.props.isSwitchedOn !== prevProps.isSwitchedOn so
meta synchronization executes even when onChange is not set.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 13dbf9d9-82a0-4e3a-bf70-c9cedc65dcd3

📥 Commits

Reviewing files that changed from the base of the PR and between 2b9ece6 and c2788cb.

📒 Files selected for processing (1)
  • app/client/src/widgets/SwitchWidget/widget/index.tsx

Comment thread app/client/src/widgets/SwitchWidget/widget/index.tsx Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a stale-binding issue where Switch1.isSwitchedOn meta can fall out of sync with programmatic updates to the switch state after the user has interacted with the widget.

Changes:

  • Adds componentDidUpdate logic in SwitchWidget to sync the isSwitchedOn meta value when the rendered switch state changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +436 to +444
// Sync meta when isSwitchedOn changes programmatically so dependents don't see a stale value.
if (
this.props.isSwitchedOn !== prevProps.isSwitchedOn &&
this.props.onChange
) {
this.props.updateWidgetMetaProperty(
"isSwitchedOn",
this.props.isSwitchedOn,
);
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sync block is gated by this.props.onChange, but onChange is optional and often unset in the repro (programmatic setValue/bindings can update defaultSwitchState without configuring the Switch’s own onChange). In that case this code never runs and isSwitchedOn meta can still go stale. Remove the && this.props.onChange guard (and, if you want to avoid extra dispatches, consider keying the sync specifically off defaultSwitchState changes instead of isSwitchedOn changes).

Copilot uses AI. Check for mistakes.
Comment on lines +436 to +444
// Sync meta when isSwitchedOn changes programmatically so dependents don't see a stale value.
if (
this.props.isSwitchedOn !== prevProps.isSwitchedOn &&
this.props.onChange
) {
this.props.updateWidgetMetaProperty(
"isSwitchedOn",
this.props.isSwitchedOn,
);
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change fixes a regression scenario (programmatic updates after a manual toggle) but there doesn’t appear to be an automated test covering it. Please add a Cypress regression that: toggles the Switch once directly (to set meta), then changes it via Switch1.setValue(...)/another widget, and asserts dependents bound to {{Switch1.isSwitchedOn}} update correctly.

Copilot uses AI. Check for mistakes.
- Remove the `&& this.props.onChange` condition so the meta sync also
  runs for Switches that only act as inputs to bindings (no onChange
  action configured) — this was the actual repro in appsmithorg#41566.
- Add a Switch_spec regression covering: user toggles once to set meta,
  then programmatic defaultSwitchState change, then assert that a
  dependent bound to Switch.isSwitchedOn updates.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@itsmejay80
Copy link
Copy Markdown
Author

itsmejay80 commented Apr 18, 2026

Thanks for the review. Addressed both items in 7f655f5:

  • Dropped the && this.props.onChange guard on the meta-sync block you're right that the repro in [Bug]: .isSwitched of a Switch-widget doesn't get the correct (updates) value #41566 doesn't require an onChange handler and the guard was preventing the fix from firing in exactly that case.
  • Added a Cypress regression in Switch_spec.js that toggles the Switch once (to set meta), then changes defaultSwitchState programmatically and asserts a dependent bound to {{Toggler.isSwitchedOn}} reflects the new value.

Note: CheckboxWidget.componentDidUpdate has the same guard pattern. I left it alone in this PR to keep scope tight, but happy to open a follow-up if maintainers think it's worth fixing there too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: .isSwitched of a Switch-widget doesn't get the correct (updates) value

2 participants