fix: resolve paneldynamic self-referential binding bug#195
fix: resolve paneldynamic self-referential binding bug#195ihsankahveci wants to merge 1 commit intokc-pit-2026-testfrom
Conversation
…k array data Break the two-way binding conflict where non_family_network's panelCount bound to itself, causing the numeric count to overwrite the person-object array in 28 survey records. - Rename non_family_network_size → network_size_agg - Rename non_family_network → network_list - Add hidden network_size_list expression as binding intermediary - panelCount now binds to network_size_list instead of self-referencing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes a SurveyJS paneldynamic configuration bug where a self-referential bindings.panelCount overwrote the panel’s array data, by renaming the affected fields and introducing an intermediary variable intended to separate “count” from “list”.
Changes:
- Renamed the network-size question field (
non_family_network_size→network_size_agg). - Renamed the paneldynamic field (
non_family_network→network_list) and changedpanelCountbinding to a new variable (network_size_list). - Added a hidden “bridge” element intended to seed
network_size_listfromnetwork_size_agg.
| { | ||
| "name": "network_size_bridge", | ||
| "title": "Network Module", | ||
| "elements": [ | ||
| { | ||
| "type": "expression", | ||
| "name": "network_size_list", | ||
| "visible": false, | ||
| "expression": "{network_size_agg}" | ||
| } | ||
| ] | ||
| }, |
There was a problem hiding this comment.
network_size_bridge is added as a new page between network_questions_p1 and network_questions_p2, but it has no visible elements. This will insert an extra blank step in the survey flow. Consider moving network_size_list into an existing page (e.g., network_questions_p2) as a hidden element, or mark this page itself as not visible so it doesn’t appear in navigation.
| "type": "expression", | ||
| "name": "network_size_list", | ||
| "visible": false, | ||
| "expression": "{network_size_agg}" |
There was a problem hiding this comment.
network_size_list is implemented as an expression question (expression: "{network_size_agg}"). Expression questions continuously recompute their value from the expression, which can overwrite updates coming from the paneldynamic bindings.panelCount when panels are added/removed. To make this a true “seed then mutate” bridge, use a value that is only initialized from network_size_agg (e.g., a hidden question with a defaultValue/defaultValueExpression) rather than a continuously calculated expression.
| "type": "expression", | |
| "name": "network_size_list", | |
| "visible": false, | |
| "expression": "{network_size_agg}" | |
| "type": "text", | |
| "name": "network_size_list", | |
| "visible": false, | |
| "readOnly": true, | |
| "defaultValueExpression": "{network_size_agg}" |
| "name": "non_family_network", | ||
| "title": "For those {non_family_network_size} people, please fill in as much of the following information as you are able:\n", | ||
| "name": "network_list", | ||
| "title": "For those {network_size_agg} people, please fill in as much of the following information as you are able:\n", |
There was a problem hiding this comment.
The panel title interpolates {network_size_agg}, but the actual panel count is bound to network_size_list. If the interviewer adds/removes panels, the title can become inaccurate. Consider referencing the bound count variable (or another value that tracks the current panel count) so the UI stays consistent with the data being collected.
| "title": "For those {network_size_agg} people, please fill in as much of the following information as you are able:\n", | |
| "title": "For those {network_size_list} people, please fill in as much of the following information as you are able:\n", |
📄 Description
The
non_family_networkpaneldynamic element had itsbindings.panelCountset to"non_family_network"— its own name. This created a two-way binding conflict where SurveyJS's numeric panel count overwrote the array of person objects, corrupting 28 survey records with a bare number (1–7) instead of the expected array.Fix: Break the self-referential binding by introducing a hidden intermediary variable and renaming fields to clearly separate concerns:
non_family_network_size→network_size_agg(self-reported count, untouched)network_size_list(hidden expression, seeded fromnetwork_size_agg, updated by panel add/remove)non_family_network→network_list(paneldynamic, stores array of person objects only)panelCountnow binds tonetwork_size_listinstead of self-referencing✅ Checklist
🔗 Related Issues
Resolves #194
💡 Type of change
🧪 How to test
npm run devinclient/network_listshould be an array of 3 objects,network_size_aggshould be the original number📝 Notes to reviewers
Breaking change for existing data: Renaming these fields means new surveys will use
network_size_agg,network_size_list, andnetwork_list. Existing records in MongoDB still havenon_family_network_sizeandnon_family_network. Any downstream analysis or data export code will need to account for both old and new field names.