🚨 CRITICAL FIX: Search filtering with Main Pager synchronization

Merge pull request #4427 from expsa/eltayar - CRITICAL FIX

🚨 CRITICAL FIX: Search filtering with Main Pager synchronization

Major fixes implemented:
- Fixed DOM filtering logic with intersection detection between filtered IDs and available DOM IDs
- Added _forceUpdateMainPager with 4 fallback methods to ensure Odoo's main pager always updates
- Enhanced debugging logs for better troubleshooting and flow tracking
- Improved _showNoResults to properly update main pager count to 0 for empty results
- Fixed state synchronization to ensure consistent updates across all UI elements
- Added comprehensive error handling and fallback methods for different Odoo versions

This resolves the critical issue where:
1. Search results showed correct count in custom counter but list didn't filter properly
2. Empty search results didn't update the main Odoo pager count
3. Search and clear operations weren't properly synchronized across all UI components
This commit is contained in:
Mohamed Eltayar 2025-08-29 21:15:06 +03:00 committed by GitHub
commit 9bd93f5138
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 151 additions and 87 deletions

View File

@ -247,37 +247,46 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
if (count === 0) {
this._showNoResults();
// CRITICAL: Update main pager for empty results
this._forceUpdateMainPager(0);
return;
}
// Update the view with filtered results - CRITICAL FIX
// Update the view with filtered results
this._updateViewWithFilteredData(records);
},
/**
* Update view with filtered data - COMPLETELY REWRITTEN
* Update view with filtered data - FIXED CRITICAL LOGIC
*/
_updateViewWithFilteredData: function(records) {
var self = this;
console.log('=== _updateViewWithFilteredData ===');
console.log('Records count:', records.length);
console.log('Filtered IDs:', this._search.filteredIds);
// Method 1: Try to filter existing DOM rows first
// ALWAYS try to update the view, regardless of DOM filtering success
// Method 1: Try DOM filtering first (fastest if it works)
var domFilterWorked = this._filterExistingRows();
console.log('DOM filtering worked:', domFilterWorked);
if (domFilterWorked) {
// Update pager with correct count
this._updatePager(records.length);
// DOM filtering worked, but STILL update pager properly
this._forceUpdateMainPager(records.length);
return;
}
// Method 2: Update the actual data and re-render
// Method 2: DOM filtering failed, need to re-render with filtered data
console.log('DOM filtering failed, re-rendering...');
this._updateStateAndRerender(records);
},
/**
* Filter existing rows in DOM - ENHANCED METHOD
* Filter existing rows in DOM - ENHANCED WITH BETTER LOGGING
*/
_filterExistingRows: function() {
if (!this._search.filteredIds || this._search.filteredIds.length === 0) {
console.log('No filtered IDs to work with');
return false;
}
@ -286,33 +295,58 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
var limit = this.state.limit || 80;
var visibleCount = 0;
var foundAnyMatch = false;
var availableRowIds = [];
console.log('Filtering rows. Total rows:', $allRows.length, 'Filtered IDs:', this._search.filteredIds);
console.log('=== DOM Filtering Debug ===');
console.log('Total rows in DOM:', $allRows.length);
console.log('Looking for IDs:', this._search.filteredIds);
console.log('Limit:', limit);
// First pass: hide all rows
$allRows.hide();
// Second pass: show matching rows up to limit
// First, collect all available row IDs for debugging
$allRows.each(function(index) {
var $row = $(this);
var rowId = self._getRowId($row);
if (rowId) {
availableRowIds.push(rowId);
}
});
console.log('Available row IDs in DOM:', availableRowIds);
// Check if any of our filtered IDs exist in DOM
var intersection = this._search.filteredIds.filter(function(id) {
return availableRowIds.includes(id);
});
console.log('Intersection (IDs that exist in DOM):', intersection);
if (intersection.length === 0) {
console.log('No matching IDs found in DOM - need to re-render');
return false;
}
// Hide all rows first
$allRows.hide();
// Show matching rows up to limit
$allRows.each(function(index) {
var $row = $(this);
var rowId = self._getRowId($row);
console.log('Row', index, 'ID:', rowId, 'Should show:', self._search.filteredIds.includes(rowId));
if (rowId && self._search.filteredIds.includes(rowId)) {
if (visibleCount < limit) {
$row.show();
visibleCount++;
foundAnyMatch = true;
console.log('Showing row', index, 'with ID', rowId);
console.log('✓ Showing row', index, 'with ID', rowId);
} else {
console.log('✗ Hiding row', index, 'with ID', rowId, '(over limit)');
}
}
});
console.log('DOM filtering result - Found matches:', foundAnyMatch, 'Visible count:', visibleCount);
// If no matches found in DOM, we need to re-render
return foundAnyMatch;
console.log('DOM filtering completed - Visible rows:', visibleCount, 'Found matches:', foundAnyMatch);
return foundAnyMatch && visibleCount > 0;
},
/**
@ -323,74 +357,111 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
var limit = this.state.limit || 80;
var pageRecords = records.slice(0, limit);
console.log('Re-rendering with filtered data. Total records:', records.length, 'Page records:', pageRecords.length);
console.log('=== Re-rendering ===');
console.log('Total records:', records.length);
console.log('Page records:', pageRecords.length);
// Update state
if (this.state && this.state.data) {
this.state.data.records = pageRecords;
this.state.count = records.length;
// Update state with filtered data
if (this.state) {
if (this.state.data) {
this.state.data.records = pageRecords;
}
this.state.count = records.length; // CRITICAL: Update count
this.state.res_ids = this._search.filteredIds;
}
// Clear existing rows
// Clear existing content
this.$('tbody .o_data_row').remove();
this.$('.oe_no_results').remove();
// Try different rendering approaches
this._tryMultipleRenderMethods(pageRecords);
// Create new rows with filtered data
if (pageRecords.length > 0) {
this._createRowsManually(pageRecords);
} else {
this._showNoResults();
}
// Update pager
this._updatePager(records.length);
// CRITICAL: Force update main pager
this._forceUpdateMainPager(records.length);
},
/**
* Try multiple rendering methods - NEW ENHANCED METHOD
* CRITICAL FIX: Force update main Odoo pager
*/
_tryMultipleRenderMethods: function(records) {
var self = this;
var renderSuccess = false;
_forceUpdateMainPager: function(totalCount) {
console.log('=== Updating Main Pager ===');
console.log('Total count:', totalCount);
// Method 1: Try Odoo's _renderRows if available
if (!renderSuccess && typeof this._renderRows === 'function') {
// Method 1: Try standard pager update
if (this.getParent() && this.getParent().pager) {
try {
var $rows = this._renderRows();
if ($rows && $rows.length > 0) {
this.$('tbody').append($rows);
renderSuccess = true;
console.log('Render method 1 succeeded');
}
console.log('Trying method 1: getParent().pager.updateState');
this.getParent().pager.updateState({
current_min: totalCount > 0 ? 1 : 0,
size: totalCount,
limit: this.state.limit || 80
});
console.log('✓ Method 1 succeeded');
return;
} catch (err) {
console.warn('Render method 1 failed:', err);
console.warn('Method 1 failed:', err);
}
}
// Method 2: Try _renderBody if available
if (!renderSuccess && typeof this._renderBody === 'function') {
try {
var result = this._renderBody();
if (result) {
if (typeof result.then === 'function') {
result.then(function() {
console.log('Render method 2 succeeded (async)');
});
} else {
console.log('Render method 2 succeeded (sync)');
}
renderSuccess = true;
}
} catch (err) {
console.warn('Render method 2 failed:', err);
// Method 2: Try alternative pager access
try {
var controller = this.getParent();
while (controller && !controller.pager) {
controller = controller.getParent();
}
if (controller && controller.pager) {
console.log('Trying method 2: controller.pager');
controller.pager.updateState({
current_min: totalCount > 0 ? 1 : 0,
size: totalCount,
limit: this.state.limit || 80
});
console.log('✓ Method 2 succeeded');
return;
}
} catch (err) {
console.warn('Method 2 failed:', err);
}
// Method 3: Manual row creation (fallback)
if (!renderSuccess) {
console.log('Using manual row creation fallback');
this._createRowsManually(records);
renderSuccess = true;
// Method 3: Direct state update + trigger change
try {
console.log('Trying method 3: direct state update');
if (this.state) {
this.state.count = totalCount;
// Trigger a state change event
this.trigger_up('reload', {
keepChanges: true,
currentId: this.state.res_id
});
console.log('✓ Method 3 triggered');
}
} catch (err) {
console.warn('Method 3 failed:', err);
}
return renderSuccess;
// Method 4: Update DOM directly if all else fails
try {
console.log('Trying method 4: direct DOM update');
var $pager = this.$el.closest('.o_content').find('.o_pager_value');
if ($pager.length) {
var displayText = totalCount > 0 ? '1-' + Math.min(totalCount, this.state.limit || 80) : '0';
$pager.text(displayText);
console.log('✓ Method 4 succeeded');
}
var $pagerSize = this.$el.closest('.o_content').find('.o_pager_size');
if ($pagerSize.length) {
$pagerSize.text(totalCount);
console.log('✓ Updated pager size directly');
}
} catch (err) {
console.warn('Method 4 failed:', err);
}
},
/**
@ -442,7 +513,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
},
/**
* Create cell for specific field - NEW HELPER METHOD
* Create cell for specific field - HELPER METHOD
*/
_createCellForField: function(record, col) {
var fieldName = col.attrs.name;
@ -535,23 +606,9 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
return parseInt(match[1]);
}
console.warn('Could not determine row ID for row:', $row[0]);
return null;
},
/**
* Update pager
*/
_updatePager: function(totalCount) {
if (this.getParent() && this.getParent().pager) {
this.getParent().pager.updateState({
current_min: totalCount > 0 ? 1 : 0,
size: totalCount,
limit: this.state.limit || 80
});
}
},
/**
* Client-side search fallback - ENHANCED
*/
@ -601,7 +658,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
this._showNoResults();
}
this._updatePager(visible);
// CRITICAL: Update main pager
this._forceUpdateMainPager(visible);
console.log('Client-side search completed. Visible:', visible, 'IDs:', matchedIds);
},
@ -610,7 +668,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
* Clear search - ENHANCED
*/
_clearSearch: function() {
console.log('Clearing search');
console.log('=== Clearing search ===');
// Clear UI
this.$('.oe_search_input').val('');
@ -627,6 +685,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
// Restore original data
if (this._search.originalData) {
console.log('Restoring original data:', this._search.originalData);
// Restore state
if (this.state) {
if (this.state.data) {
@ -645,8 +705,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
$(this).toggle(index < limit);
});
// Restore pager
this._updatePager(this._search.originalData.count);
// CRITICAL: Restore main pager
this._forceUpdateMainPager(this._search.originalData.count);
// Clear stored original data
this._search.originalData = null;
@ -664,11 +724,11 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
});
if (this.state) {
this._updatePager(this.state.count || $rows.length);
this._forceUpdateMainPager(this.state.count || $rows.length);
}
}
console.log('Search cleared');
console.log('Search cleared successfully');
},
/**
@ -801,9 +861,11 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
},
/**
* Show no results message
* Show no results message - ENHANCED
*/
_showNoResults: function() {
console.log('Showing no results message');
// Remove existing message
this.$('.oe_no_results').remove();
@ -819,6 +881,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
'</td></tr>';
this.$('tbody').append(html);
console.log('No results message displayed');
},
/**