[FIX] web: reset renderer local state when switching view

before this commit: when switching to form view from listview using Create
button and then activate some other tab and Discard that record which will
move back user to list view now again clicking Create button opens form view
but active tab is last activated form tab instead of first one, this is because
of local state is not cleared.

after this commit: when form view is switched back to list view using Discard
button, local state will be cleared, here we are explicitly removing 'active'
class from all tab and pages of all notebooks.

task-2466057

X-original-commit: ff0e5694e28a46287dc54ab440364e11e8e9c832
This commit is contained in:
Mohammed Shekha
2021-07-02 12:48:45 +00:00
parent ad434daf0f
commit afa4ac684d
4 changed files with 76 additions and 0 deletions
@@ -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.
@@ -91,6 +91,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
if (this._boundOnBeforeUnload) {
window.removeEventListener("beforeunload", this._boundOnBeforeUnload);
}
this.renderer.resetLocalState();
},
//--------------------------------------------------------------------------
@@ -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.
@@ -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': `<form>
<sheet>
<field name="product_id"/>
<notebook>
<page string="Foo">
<field name="foo"/>
</page>
<page string="Bar">
<field name="bar"/>
</page>
</notebook>
</sheet>
</form>`,
'partner,false,list': '<tree><field name="foo"/></tree>',
'partner,false,search': '<search></search>',
};
serverData.actions = {
1: {
id: 1,
name: 'Partner',
res_model: 'partner',
type: 'ir.actions.act_window',
views: [[false, 'list'], [false, 'form']],
}
};
const webClient = await createWebClient({ serverData });
await doAction(webClient, 1);
await testUtils.dom.click(webClient.el.querySelector('.o_list_button_add'));
assert.containsOnce(webClient, '.o_form_view');
// click on second page tab
await testUtils.dom.click($(webClient.el).find('.o_notebook .nav-link:eq(1)'));
await testUtils.dom.click('.o_control_panel .o_form_button_cancel');
await legacyExtraNextTick();
assert.containsNone(webClient, '.o_form_view');
await testUtils.dom.click(webClient.el.querySelector('.o_list_button_add'));
await legacyExtraNextTick();
// check notebook active page is 0th page
assert.hasClass($(webClient.el).find('.o_notebook .nav-link:eq(0)'), 'active');
});
QUnit.test('rendering stat buttons', async function (assert) {
assert.expect(3);