Skip to content

Fix Param widget not reflecting value changes made in own callback - #8492

Merged
philippjfr merged 4 commits into
holoviz:mainfrom
SuMayaBee:fix/param-model-callback-update
Mar 12, 2026
Merged

Fix Param widget not reflecting value changes made in own callback#8492
philippjfr merged 4 commits into
holoviz:mainfrom
SuMayaBee:fix/param-model-callback-update

Conversation

@SuMayaBee

@SuMayaBee SuMayaBee commented Mar 8, 2026

Copy link
Copy Markdown
Contributor

Description

This PR fixes an issue where pn.widgets built from a param.Parameterized model do not update in the UI when their value is changed inside their own @param.depends callback. The param model updates correctly, but the change is never reflected in the frontend.

Problem:
When a @param.depends callback modifies its own parameter, the widget doesn't reflect the new value even though the param model is correct.

While investigating, I found that link_widget() holds a re-entrancy lock (updating) while syncing the param model. If a watcher fires and changes the parameter during that window, the param→widget sync (link()) sees the lock and silently returns early, leaving the widget out of sync.

Solution:
After releasing the lock, compare the current parameter value to what we originally set. If they differ, sync the widget immediately. This avoids infinite loops since it only fires when there's an actual mismatch.

Before/After UI:

📹 See attached video — before the fix, clicking the checkbox leaves it checked; after the fix, it correctly resets itself to unchecked.

Before:

PR11_before.mp4

After:

PR11after.mp4

Fixes #8159

How Has This Been Tested?

Two cases were tested to verify the fix and ensure no regressions:

  • Case 1 — Regression check: A classic pn.widgets.Checkbox with a bound function that resets itself to False. This was already working before the fix and should continue to work.
  • Case 2 — Bug fix check: A param.Parameterized model with a @param.depends callback that resets its own value. Before the fix, the param model would update correctly but the widget would stay stale in the UI. After the fix, both the param model and the widget correctly reflect False.

To reproduce, run the following code:

import panel as pn
import param

pn.extension()

# Works as expected:
# Classic panel widget checkbox with bound function that sets itself to False

widget_checkbox = pn.widgets.Checkbox(name='Widget checkbox')

@pn.depends(widget_checkbox, watch=True)
def update_checkbox(event):
    widget_checkbox.value = False
    print(f'Widget checkbox value set to {widget_checkbox.value}')


# Does not work as expected:
# Parameterized model with boolean value parameter

class ParameterizedCheckbox(param.Parameterized):
    
    value = param.Boolean(label='Parameterized checkbox')

    @param.depends('value', watch=True)
    def update(self):
        self.value = False
        print(f'ParameterizedCheckbox value set to {self.value}')


pn.Column(
    'Both of these checkboxes should uncheck themselves after being clicked.',
    widget_checkbox,
    ParameterizedCheckbox().param.value
).servable()

AI Disclosure

  • This PR contains AI-generated content.
    • I have tested all AI-generated content in my PR.
    • I take responsibility for all AI-generated content in my PR.
      Tools: Gemini 3 Flash - Used to analyze the bug and identify the root cause and the implementation.

Checklist

  • Tests added and is passing
  • Added documentation

@codecov

codecov Bot commented Mar 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.04%. Comparing base (4e06893) to head (d9bbc7e).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main    #8492       +/-   ##
===========================================
+ Coverage   70.32%   86.04%   +15.71%     
===========================================
  Files         348      349        +1     
  Lines       55093    55114       +21     
===========================================
+ Hits        38744    47421     +8677     
+ Misses      16349     7693     -8656     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@SuMayaBee

Copy link
Copy Markdown
Contributor Author

@philippjfr any suggestions?

@philippjfr

Copy link
Copy Markdown
Member

@SuMayaBee, the fix makes sense to me, though we do need some tests.

@SuMayaBee

SuMayaBee commented Mar 12, 2026

Copy link
Copy Markdown
Contributor Author

@SuMayaBee, the fix makes sense to me, though we do need some tests.

@philippjfr I've added a parametrized test test_param_widget_updates_from_own_callback that covers both Boolean and Number parameter types. It verifies that when a @param.depends callback modifies its own parameter, both the param model and the widget reflect the updated value.

@philippjfr

Copy link
Copy Markdown
Member

Nice, thank you @SuMayaBee!

@philippjfr
philippjfr merged commit 9837859 into holoviz:main Mar 12, 2026
17 of 18 checks passed
@github-actions

Copy link
Copy Markdown

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jun 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panel widgets based on param model not updating when changed in own callback

2 participants