diff --git a/packages/devextreme/js/__internal/ui/tab_panel/m_tab_panel.ts b/packages/devextreme/js/__internal/ui/tab_panel/m_tab_panel.ts index 3acd280a8031..14d50450bdc6 100644 --- a/packages/devextreme/js/__internal/ui/tab_panel/m_tab_panel.ts +++ b/packages/devextreme/js/__internal/ui/tab_panel/m_tab_panel.ts @@ -489,7 +489,7 @@ const TabPanel = MultiView.inherit({ break; case 'focusedElement': { const id = value ? $(value).index() : value; - const newItem = value ? this._tabs._itemElements().eq(id) : value; + const newItem = value && this._tabs ? this._tabs._itemElements().eq(id) : value; this._setTabsOption('focusedElement', getPublicElement(newItem)); if (value) { diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets/tabPanel.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets/tabPanel.tests.js index 26a956886d9c..a9d545ffca7c 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets/tabPanel.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets/tabPanel.tests.js @@ -1296,3 +1296,225 @@ QUnit.module('Tabs Indicator position', () => { assert.ok($tabs.hasClass(TABS_INDICATOR_POSITION_CLASS.left)); }); }); + +QUnit.module('selectedIndex vs items.visible', () => { + QUnit.module('on init', () => { + QUnit.test('selectedIndex should be updated to the next visible item if initially selected item is hidden', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: false }, + { text: '3', visible: true }, + ], + selectedIndex: 1 + }); + const instance = $tabPanel.dxTabPanel('instance'); + + assert.strictEqual(instance.option('selectedIndex'), 2, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('selectedIndex should be updated to the next visible item to the left if initially selected item is hidden and RTL is enabled', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: false }, + { text: '3', visible: true }, + ], + selectedIndex: 1, + rtlEnabled: true + }); + const instance = $tabPanel.dxTabPanel('instance'); + + assert.strictEqual(instance.option('selectedIndex'), 0, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('selectedIndex should be zero when all items are not visible', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: false }, + { text: '2', visible: false }, + { text: '3', visible: false }, + ], + selectedIndex: 1 + }); + const instance = $tabPanel.dxTabPanel('instance'); + + assert.strictEqual(instance.option('selectedIndex'), 0, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('next visible item should be selected if currently selected item is hidden and loop=true', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: false }, + { text: '3', visible: false }, + ], + selectedIndex: 2, + loop: true + }); + const instance = $tabPanel.dxTabPanel('instance'); + + assert.strictEqual(instance.option('selectedIndex'), 0, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('first visible item should be selected if current selected item is hidden and it is in the end and loop = true', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: true }, + { text: '3', visible: false }, + ], + selectedIndex: 2, + loop: true + }); + const instance = $tabPanel.dxTabPanel('instance'); + + assert.strictEqual(instance.option('selectedIndex'), 0, 'selectedIndex is updated on proper index'); + }); + }); + + QUnit.module('on runtime', () => { + QUnit.test('selectedIndex should be updated to the next visible item if it is changed to a hidden item', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: false }, + { text: '3', visible: true }, + ] + }); + const instance = $tabPanel.dxTabPanel('instance'); + instance.option('selectedIndex', 1); + + assert.strictEqual(instance.option('selectedIndex'), 2, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('selectedIndex should be set to zero if all items became hidden', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: false }, + { text: '3', visible: true }, + ], + selectedIndex: 2 + }); + const instance = $tabPanel.dxTabPanel('instance'); + instance.option({ + items: [ + { text: '1', visible: false }, + { text: '2', visible: false }, + { text: '3', visible: false }, + ] + }); + + assert.strictEqual(instance.option('selectedIndex'), 0, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('when hiding selected item selectedIndex should be set to next visible item', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: true }, + { text: '3', visible: true }, + ], + selectedIndex: 1 + }); + const instance = $tabPanel.dxTabPanel('instance'); + instance.option('items[1].visible', false); + + assert.strictEqual(instance.option('selectedIndex'), 2, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('when hiding non-selected item before selectedIndex, selectedIndex should not change', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: true }, + { text: '3', visible: true }, + ], + selectedIndex: 2 + }); + const instance = $tabPanel.dxTabPanel('instance'); + instance.option('items[1].visible', false); + + assert.strictEqual(instance.option('selectedIndex'), 2, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('when hiding selected item positioned in the end, next visible item to the left is selected', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: true }, + { text: '3', visible: true }, + ], + selectedIndex: 2 + }); + const instance = $tabPanel.dxTabPanel('instance'); + instance.option('items[2].visible', false); + + assert.strictEqual(instance.option('selectedIndex'), 1, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('when showing previously invisible item before selectedIndex, selectedIndex should not change', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: false }, + { text: '3', visible: true }, + ], + selectedIndex: 2 + }); + const instance = $tabPanel.dxTabPanel('instance'); + instance.option('items[1].visible', true); + + assert.strictEqual(instance.option('selectedIndex'), 2, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('when showing previously invisible item after selectedIndex, selectedIndex should not change', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: false }, + { text: '3', visible: true }, + ], + selectedIndex: 0 + }); + const instance = $tabPanel.dxTabPanel('instance'); + instance.option('items[1].visible', true); + + assert.strictEqual(instance.option('selectedIndex'), 0, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('when hiding last visible item selectedIndex should return to 0 index', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: false }, + { text: '2', visible: false }, + { text: '3', visible: true }, + ], + selectedIndex: 2 + }); + const instance = $tabPanel.dxTabPanel('instance'); + instance.option('items[2].visible', false); + + assert.strictEqual(instance.option('selectedIndex'), 0, 'selectedIndex is updated on proper index'); + }); + + QUnit.test('after removing selected item selectedIndex should be restored to 0', function(assert) { + const $tabPanel = $('#tabPanel').dxTabPanel({ + items: [ + { text: '1', visible: true }, + { text: '2', visible: true }, + { text: '3', visible: true }, + ], + selectedIndex: 2 + }); + const instance = $tabPanel.dxTabPanel('instance'); + instance.option('items', [ + { text: '1', visible: true }, + { text: '2', visible: true }, + ]); + + assert.strictEqual(instance.option('selectedIndex'), 0, 'selectedIndex is not changed'); + }); + }); +});