diff --git a/addons/web/static/src/legacy/js/views/abstract_renderer.js b/addons/web/static/src/legacy/js/views/abstract_renderer.js index 27dd35aa7a7..f30541c2010 100644 --- a/addons/web/static/src/legacy/js/views/abstract_renderer.js +++ b/addons/web/static/src/legacy/js/views/abstract_renderer.js @@ -88,6 +88,15 @@ export default mvc.Renderer.extend({ */ giveFocus: function () { }, + /** + * Resets state that renderer keeps, state may contains scroll position, + * the currently active tab page, ... + * + * @see getLocalState + * @see setLocalState + */ + resetLocalState() { + }, /** * This is the reverse operation from getLocalState. With this method, we * expect the renderer to restore all DOM state, if it is relevant. diff --git a/addons/web/static/src/legacy/js/views/basic/basic_controller.js b/addons/web/static/src/legacy/js/views/basic/basic_controller.js index 22ca19992ac..24daed9bcf7 100644 --- a/addons/web/static/src/legacy/js/views/basic/basic_controller.js +++ b/addons/web/static/src/legacy/js/views/basic/basic_controller.js @@ -91,6 +91,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { if (this._boundOnBeforeUnload) { window.removeEventListener("beforeunload", this._boundOnBeforeUnload); } + this.renderer.resetLocalState(); }, //-------------------------------------------------------------------------- diff --git a/addons/web/static/src/legacy/js/views/form/form_renderer.js b/addons/web/static/src/legacy/js/views/form/form_renderer.js index db6adb77d38..512b39dfe07 100644 --- a/addons/web/static/src/legacy/js/views/form/form_renderer.js +++ b/addons/web/static/src/legacy/js/views/form/form_renderer.js @@ -256,6 +256,21 @@ var FormRenderer = BasicRenderer.extend({ resetLastActivatedField: function () { this.lastActivatedFieldIndex = -1; }, + /** + * Resets state which stores information like scroll position, curently + * active page, ... + * + * @override + */ + resetLocalState() { + for (const notebook of this.el.querySelectorAll(':scope div.o_notebook')) { + [...notebook.querySelectorAll(':scope .o_notebook_headers .nav-item .nav-link')] + .map(nav => nav.classList.remove('active')); + [...notebook.querySelectorAll(':scope .tab-content > .tab-pane')] + .map(tab => tab.classList.remove('active')); + } + + }, /** * Restore active tab pages for each notebook. It relies on the implicit fact * that each nav header corresponds to a tab page. diff --git a/addons/web/static/tests/legacy/views/form_tests.js b/addons/web/static/tests/legacy/views/form_tests.js index e2ee4864c79..442065b76ce 100644 --- a/addons/web/static/tests/legacy/views/form_tests.js +++ b/addons/web/static/tests/legacy/views/form_tests.js @@ -1062,6 +1062,57 @@ QUnit.module('Views', { form.destroy(); }); + QUnit.test('reset local state when switching to another view', async function (assert) { + assert.expect(3); + + serverData.views = { + 'partner,false,form': `
`, + 'partner,false,list': '