🔥 CRITICAL: Fix infinite search loop - prevent reload cycles
Merge pull request #4428 - CRITICAL FIX: Infinite Loop Prevention 🔥 CRITICAL: Fix infinite search loop - prevent reload cycles This resolves the critical flickering issue where search results would appear correctly for a split second then revert to showing all records in an endless loop. Key fixes: - Added _searchInProgress flag to prevent infinite search loops - Removed trigger_up('reload') that was causing view re-renders during search - Enhanced _renderView to only re-apply search on manual page loads, not during search operations - Replaced _forceUpdateMainPager with safe _updatePagerOnly using direct DOM updates - Added comprehensive loop prevention in _performSearch and _clearSearch - Fixed infinite cycle: search → pager update → view reload → search → repeat The search functionality now works stably without any flickering or reload cycles.
This commit is contained in:
commit
e5a9ba3b8a
|
|
@ -30,9 +30,9 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
_renderView: function () {
|
||||
var self = this;
|
||||
|
||||
// Store search state before render
|
||||
// PREVENT INFINITE LOOP: Don't re-trigger search during render
|
||||
var searchValue = this._search ? this._search.value : '';
|
||||
var hasActiveSearch = searchValue && searchValue.length > 0;
|
||||
var isCurrentlySearching = this._search && this._search.isFiltered;
|
||||
|
||||
return this._super.apply(this, arguments).then(function () {
|
||||
// Add search box if needed
|
||||
|
|
@ -47,10 +47,11 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
// Always restore search UI
|
||||
self._restoreSearchUI();
|
||||
|
||||
// If we had an active search, re-apply it after a short delay
|
||||
if (hasActiveSearch) {
|
||||
// CRITICAL FIX: Only re-apply search if it's a manual page load, NOT during search operations
|
||||
if (searchValue && !isCurrentlySearching && !self._searchInProgress) {
|
||||
console.log('Re-applying search after page load:', searchValue);
|
||||
setTimeout(function() {
|
||||
if (self._search && self._search.value) {
|
||||
if (self._search && self._search.value && !self._searchInProgress) {
|
||||
self._performSearch(self._search.value);
|
||||
}
|
||||
}, 100);
|
||||
|
|
@ -71,7 +72,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
'<input type="text" class="oe_search_input" placeholder="' + _t('Search...') + '" style="flex: 1; border: 1px solid #ccc; height: 32px; padding: 0 12px; border-radius: 4px;">' +
|
||||
'<button class="btn btn-sm btn-secondary oe_clear_search ml-2" style="display: none;">' + _t('Clear') + '</button>' +
|
||||
'<span class="oe_search_count ml-2" style="display: none; color: #6c757d; font-size: 0.9em;"></span>' +
|
||||
'<span class="oe_search_loading ml-2" style="display: none;"><i class="fa fa-spinner fa-spin"></i></span>' +
|
||||
'<span class="oe_search_loading ml-2" style="display: none;"><i class="fa fa-spinner fa-spin\"></i></span>' +
|
||||
'</div>';
|
||||
this.$el.prepend($(html));
|
||||
},
|
||||
|
|
@ -92,6 +93,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
isFiltered: false,
|
||||
lastSearchPromise: null
|
||||
};
|
||||
// Add flag to prevent infinite loops
|
||||
this._searchInProgress = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -161,24 +164,38 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
},
|
||||
|
||||
/**
|
||||
* Perform search - THE MAIN SEARCH LOGIC
|
||||
* Perform search - ENHANCED WITH LOOP PREVENTION
|
||||
*/
|
||||
_performSearch: function(value) {
|
||||
var self = this;
|
||||
|
||||
// PREVENT INFINITE LOOPS
|
||||
if (this._searchInProgress) {
|
||||
console.log('Search already in progress, ignoring');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Use mutex to prevent concurrent searches
|
||||
return this._searchMutex.exec(function() {
|
||||
// Set flag to prevent loops
|
||||
self._searchInProgress = true;
|
||||
|
||||
// Clear if empty
|
||||
if (!value) {
|
||||
return self._clearSearch();
|
||||
return self._clearSearch().finally(function() {
|
||||
self._searchInProgress = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Check prerequisites
|
||||
if (!self.state || !self.state.model) {
|
||||
console.error('Missing model information');
|
||||
return;
|
||||
self._searchInProgress = false;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
console.log('=== Starting search for:', value, '===');
|
||||
|
||||
// Store original data on first search
|
||||
if (!self._search.originalData && !self._search.isFiltered) {
|
||||
self._storeOriginalData();
|
||||
|
|
@ -227,6 +244,9 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
}
|
||||
}).finally(function() {
|
||||
self._showLoading(false);
|
||||
// CRITICAL: Clear the progress flag
|
||||
self._searchInProgress = false;
|
||||
console.log('=== Search completed ===');
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
@ -237,6 +257,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
_processSearchResults: function(records) {
|
||||
var count = records.length;
|
||||
|
||||
console.log('Processing search results:', count, 'records');
|
||||
|
||||
// Update search state
|
||||
this._search.isFiltered = true;
|
||||
this._search.allFilteredRecords = records;
|
||||
|
|
@ -247,8 +269,8 @@ 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);
|
||||
// Update main pager for empty results - WITHOUT RELOAD
|
||||
this._updatePagerOnly(0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -257,22 +279,20 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
},
|
||||
|
||||
/**
|
||||
* Update view with filtered data - FIXED CRITICAL LOGIC
|
||||
* Update view with filtered data - ENHANCED TO PREVENT LOOPS
|
||||
*/
|
||||
_updateViewWithFilteredData: function(records) {
|
||||
console.log('=== _updateViewWithFilteredData ===');
|
||||
console.log('Records count:', records.length);
|
||||
console.log('Filtered IDs:', this._search.filteredIds);
|
||||
|
||||
// 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) {
|
||||
// DOM filtering worked, but STILL update pager properly
|
||||
this._forceUpdateMainPager(records.length);
|
||||
// DOM filtering worked, update pager WITHOUT causing reload
|
||||
this._updatePagerOnly(records.length);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -300,7 +320,6 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
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, collect all available row IDs for debugging
|
||||
$allRows.each(function(index) {
|
||||
|
|
@ -339,13 +358,11 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
visibleCount++;
|
||||
foundAnyMatch = true;
|
||||
console.log('✓ Showing row', index, 'with ID', rowId);
|
||||
} else {
|
||||
console.log('✗ Hiding row', index, 'with ID', rowId, '(over limit)');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('DOM filtering completed - Visible rows:', visibleCount, 'Found matches:', foundAnyMatch);
|
||||
console.log('DOM filtering completed - Visible rows:', visibleCount);
|
||||
return foundAnyMatch && visibleCount > 0;
|
||||
},
|
||||
|
||||
|
|
@ -381,21 +398,21 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
this._showNoResults();
|
||||
}
|
||||
|
||||
// CRITICAL: Force update main pager
|
||||
this._forceUpdateMainPager(records.length);
|
||||
// Update pager WITHOUT causing reload
|
||||
this._updatePagerOnly(records.length);
|
||||
},
|
||||
|
||||
/**
|
||||
* CRITICAL FIX: Force update main Odoo pager
|
||||
* SAFE PAGER UPDATE - WITHOUT RELOAD TRIGGERS
|
||||
*/
|
||||
_forceUpdateMainPager: function(totalCount) {
|
||||
console.log('=== Updating Main Pager ===');
|
||||
_updatePagerOnly: function(totalCount) {
|
||||
console.log('=== Safe Pager Update ===');
|
||||
console.log('Total count:', totalCount);
|
||||
|
||||
// Method 1: Try standard pager update
|
||||
if (this.getParent() && this.getParent().pager) {
|
||||
// Method 1: Try standard pager update (SAFEST - no reload)
|
||||
if (this.getParent() && this.getParent().pager && this.getParent().pager.updateState) {
|
||||
try {
|
||||
console.log('Trying method 1: getParent().pager.updateState');
|
||||
console.log('Trying method 1: safe pager updateState');
|
||||
this.getParent().pager.updateState({
|
||||
current_min: totalCount > 0 ? 1 : 0,
|
||||
size: totalCount,
|
||||
|
|
@ -408,13 +425,13 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
}
|
||||
}
|
||||
|
||||
// Method 2: Try alternative pager access
|
||||
// Method 2: Try alternative pager access (SAFE)
|
||||
try {
|
||||
var controller = this.getParent();
|
||||
while (controller && !controller.pager) {
|
||||
controller = controller.getParent();
|
||||
}
|
||||
if (controller && controller.pager) {
|
||||
if (controller && controller.pager && controller.pager.updateState) {
|
||||
console.log('Trying method 2: controller.pager');
|
||||
controller.pager.updateState({
|
||||
current_min: totalCount > 0 ? 1 : 0,
|
||||
|
|
@ -428,30 +445,14 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
console.warn('Method 2 failed:', err);
|
||||
}
|
||||
|
||||
// Method 3: Direct state update + trigger change
|
||||
// Method 3: Direct DOM update (SAFEST FALLBACK - no triggers)
|
||||
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);
|
||||
}
|
||||
|
||||
// Method 4: Update DOM directly if all else fails
|
||||
try {
|
||||
console.log('Trying method 4: direct DOM update');
|
||||
console.log('Trying method 3: 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');
|
||||
console.log('✓ Method 3 succeeded - updated pager value');
|
||||
}
|
||||
|
||||
var $pagerSize = this.$el.closest('.o_content').find('.o_pager_size');
|
||||
|
|
@ -459,9 +460,26 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
$pagerSize.text(totalCount);
|
||||
console.log('✓ Updated pager size directly');
|
||||
}
|
||||
|
||||
// Also try standard pager selectors
|
||||
var $standardPager = $('.o_pager_value');
|
||||
if ($standardPager.length) {
|
||||
var displayText = totalCount > 0 ? '1-' + Math.min(totalCount, this.state.limit || 80) : '0';
|
||||
$standardPager.text(displayText);
|
||||
console.log('✓ Updated standard pager');
|
||||
}
|
||||
|
||||
var $standardSize = $('.o_pager_size');
|
||||
if ($standardSize.length) {
|
||||
$standardSize.text(totalCount);
|
||||
console.log('✓ Updated standard pager size');
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Method 4 failed:', err);
|
||||
console.warn('Method 3 failed:', err);
|
||||
}
|
||||
|
||||
// REMOVED: Method that caused infinite loop (trigger_up reload)
|
||||
console.log('Pager update completed');
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -658,18 +676,27 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
this._showNoResults();
|
||||
}
|
||||
|
||||
// CRITICAL: Update main pager
|
||||
this._forceUpdateMainPager(visible);
|
||||
// Update pager safely
|
||||
this._updatePagerOnly(visible);
|
||||
|
||||
console.log('Client-side search completed. Visible:', visible, 'IDs:', matchedIds);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear search - ENHANCED
|
||||
* Clear search - ENHANCED WITH LOOP PREVENTION
|
||||
*/
|
||||
_clearSearch: function() {
|
||||
console.log('=== Clearing search ===');
|
||||
|
||||
// PREVENT LOOPS during clear
|
||||
if (this._searchInProgress) {
|
||||
console.log('Search in progress during clear, setting flag to clear after');
|
||||
this._pendingClear = true;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this._searchInProgress = true;
|
||||
|
||||
// Clear UI
|
||||
this.$('.oe_search_input').val('');
|
||||
this.$('.oe_clear_search').hide();
|
||||
|
|
@ -683,6 +710,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
this._search.isFiltered = false;
|
||||
this._search.lastSearchPromise = null;
|
||||
|
||||
var promise;
|
||||
|
||||
// Restore original data
|
||||
if (this._search.originalData) {
|
||||
console.log('Restoring original data:', this._search.originalData);
|
||||
|
|
@ -705,12 +734,14 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
$(this).toggle(index < limit);
|
||||
});
|
||||
|
||||
// CRITICAL: Restore main pager
|
||||
this._forceUpdateMainPager(this._search.originalData.count);
|
||||
// Restore pager safely
|
||||
this._updatePagerOnly(this._search.originalData.count);
|
||||
|
||||
// Clear stored original data
|
||||
this._search.originalData = null;
|
||||
this._search.originalDomain = null;
|
||||
|
||||
promise = Promise.resolve();
|
||||
} else {
|
||||
// Just show all rows with limit
|
||||
var $rows = this.$('.o_data_row');
|
||||
|
|
@ -724,11 +755,17 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
});
|
||||
|
||||
if (this.state) {
|
||||
this._forceUpdateMainPager(this.state.count || $rows.length);
|
||||
this._updatePagerOnly(this.state.count || $rows.length);
|
||||
}
|
||||
|
||||
promise = Promise.resolve();
|
||||
}
|
||||
|
||||
// Clear flags
|
||||
this._searchInProgress = false;
|
||||
console.log('Search cleared successfully');
|
||||
|
||||
return promise;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue