嵌套JSON数据填充表单与网格的两类技术问题求助
Context
You're working with nested JSON data (root AqiConfig with Type (unique) and Pollutants (hasMany) associations) to populate a form and grids. When a row in aqiGrid is clicked, subsequent components are populated. You've hit two tricky issues:
Problem 1: Cancel Button Fails After Editing Type Combobox in aqiForm
When you edit the Label field and click Cancel, changes revert correctly—but modifying the Type combobox breaks the Cancel functionality entirely.
Why This Happens
This is almost always tied to how your Type combobox interacts with the nested Type association in your AqiConfig model. Common root causes:
- The combobox isn't properly linked to the model's Type reference (e.g., mismatched
valueField/displayFieldsettings). - Your Cancel logic only rolls back changes on the root
AqiConfigmodel, not the associatedTypemodel. - Custom code in the combobox's
select/changeevents accidentally commits changes or bypasses the model's dirty state tracking.
Fixes to Try
Validate Combobox Binding
Double-check your combobox config to ensure it's correctly tied to the nested Type model:{ xtype: 'combobox', fieldLabel: 'Type', valueField: 'Id', // Matches Type model's unique ID field displayField: 'Label', // Matches Type model's display field bind: '{aqiConfig.Type.Id}', // Explicitly bind to the nested Type's ID store: typeOptionsStore, // Your preloaded Type options store forceSelection: true }This ensures selecting a Type updates the nested model correctly and marks it as dirty for rollback.
Update Cancel Logic to Handle Associations
IfTypeis ahasOneassociation onAqiConfig, make sure your Cancel handler rolls back changes on both the root model and the associated Type:cancelHandler: function() { const aqiConfig = this.getViewModel().get('aqiConfig'); // Roll back root model changes aqiConfig.rejectChanges(); // Roll back associated Type model if it exists if (aqiConfig.Type) { aqiConfig.Type.rejectChanges(); } // Refresh the form to sync view with the rolled-back model this.up('form').getForm().loadRecord(aqiConfig); }Alternatively, set
cascadeReject: truein yourAqiConfigmodel's Type association config to auto-rollback nested changes when the root model rejects changes.Check for Accidental Commit Logic
Scan the combobox'sselectorchangeevents for any code that callscommitChanges()on the model—this would lock in changes before you can cancel them.
Problem 2: Physical Combobox in aqiPollutantGrid Glitches on Edit
When editing the physical value in the grid's last column:
- The current value disappears immediately when editing starts
- Selecting a new value results in the first option being displayed instead
- Calling
rejectChanges()fixes theOptionalfield but breaks the combobox
Why This Happens
This is typically a mismatch between the combobox's configuration and the grid row model's physical field. Common issues:
- Type mismatch between the combobox's
valueFieldand the model'sphysicalfield (e.g., model stores a string ID, combobox uses numeric values) - The cell editor combobox isn't properly syncing with the model during edit/cancel
rejectChanges()rolls back the model but doesn't trigger a grid refresh, leaving the combobox in an inconsistent state
Fixes to Try
Align Combobox and Model Field Types
Ensure the combobox'svalueFieldmatches the data type of yourPollutantsmodel'sphysicalfield exactly. For example, if your model storesphysicalas a string ID, the combobox'svalueFieldshould point to the string ID in your physical options store.Improve Cell Editor Configuration
Tweak your grid column's editor to enforce valid selections and sync properly:{ text: 'Physical', dataIndex: 'physical', editor: { xtype: 'combobox', store: physicalOptionsStore, valueField: 'id', // Match your physical option's unique ID field displayField: 'label', // Match your physical option's display field forceSelection: true, queryMode: 'local', triggerAction: 'all' } }forceSelection: trueprevents invalid values, andqueryMode: 'local'ensures the dropdown loads correctly without unnecessary remote calls.Handle Canceled Edits Precisely
Instead of relying onrejectChanges()(which rolls back all fields), save the originalphysicalvalue before editing and restore it if the user cancels. Use the grid'sbeforeeditandcanceleditevents:listeners: { beforeedit: function(editor, context) { // Save original physical value for the row context.record.originalPhysical = context.record.get('physical'); }, canceledit: function(editor, context) { // Restore original value context.record.set('physical', context.record.originalPhysical); // Refresh the row to update the combobox display context.grid.getView().refreshRow(context.record); // Clean up the temporary property delete context.record.originalPhysical; } }This targets only the
physicalfield, avoiding unintended side effects on other fields likeOptional.Fix
rejectChanges()Glitch
If you still want to userejectChanges(), add a grid refresh after calling it to sync the view with the rolled-back model:// In your cancel logic record.rejectChanges(); grid.getView().refreshRow(record);This ensures the combobox re-renders with the original model value, eliminating the error.
内容的提问来源于stack exchange,提问作者mpe

