Skip to content

Commit 1918511

Browse files
authored
fix: pfe-tabs set default index to 0 if null provided (#1275)
* fix: Fix patch * fix: Add more info to the changelog * fix: Update modal script * fix: If tabset gets null selectedIndex, use 0 * fix: Revert documentation changes * fix: Revert modal updates * fix: Remove package-lock * fix: Use more explicit null and undefined values * fix: Add warning message if no tab provided * fix: Bug fix content-set and tabs * fix: Fix content set failure * fix: pfelement has a this.template so the template getter in the accordion and tabs is conflicting * fix: Remove default 0 on selectedIndex * fix: Stronger comment
1 parent 7cbd6fb commit 1918511

File tree

4 files changed

+72
-62
lines changed

4 files changed

+72
-62
lines changed

CHANGELOG-1.x.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
- [f876664](https://github.com/patternfly/patternfly-elements/commit/f876664655894cbd29d610c20b3bdbde31aaed7a) fix: Sass maps missing from compiled assets
44
- [e3fd841](https://github.com/patternfly/patternfly-elements/commit/e3fd8414cf380a45a89f4166ad2f9d9125cf8760) fix: Storybook updates required change to knobs add-on import
5-
- [](https://github.com/patternfly/patternfly-elements/commit/) fix: Remove deprecated method call in pfe-modal, _mapSchemaToSlots
5+
- [7cbd6fb](https://github.com/patternfly/patternfly-elements/commit/7cbd6fb4f879986dcf3677947ae29fe49268884f) fix: Remove deprecated method call in pfe-modal, _mapSchemaToSlots
6+
- [](https://github.com/patternfly/patternfly-elements/commit/) fix: Tabset should default to 0 if selectedIndex is set to null
67

78
## 1.1.0 ( 2020-12-22 )
89

elements/pfe-accordion/src/pfe-accordion.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class PfeAccordion extends PFElement {
7878
}
7979

8080
// Each set contains a header and a panel
81-
static get template() {
81+
static get contentTemplate() {
8282
return `
8383
<pfe-accordion-header content-type="header"></pfe-accordion-header>
8484
<pfe-accordion-panel content-type="panel"></pfe-accordion-panel>

elements/pfe-content-set/src/pfe-content-set.js

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -111,25 +111,14 @@ class PfeContentSet extends PFElement {
111111
return this.parentNode ? this.parentNode.offsetWidth > breakpointValue : window.outerWidth > breakpointValue;
112112
}
113113

114-
get tab() {
115-
// Check if the appropriate tag exists already
114+
get tabs() {
116115
return this.shadowRoot.querySelector(`${PfeTabs.tag}[visible-at="large"]`);
117116
}
118117

119118
get accordion() {
120-
// Check if the appropriate tag exists already
121119
return this.shadowRoot.querySelector(`${PfeAccordion.tag}[visible-at="small"]`);
122120
}
123121

124-
get displayTemplate() {
125-
const template = document.createElement("template");
126-
127-
// // Set up the template for the sets of content
128-
template.innerHTML = this.isTab ? PfeTabs.template : PfeAccordion.template;
129-
130-
return template;
131-
}
132-
133122
constructor() {
134123
super(PfeContentSet);
135124

@@ -203,21 +192,21 @@ class PfeContentSet extends PFElement {
203192

204193
_toggleVisible() {
205194
if (this.isTab) {
206-
if (this.tab) this.tab.removeAttribute("hidden");
195+
if (this.tabs) this.tabs.removeAttribute("hidden");
207196
if (this.accordion) this.accordion.setAttribute("hidden", "");
208197
} else {
209198
if (this.accordion) this.accordion.removeAttribute("hidden");
210-
if (this.tab) this.tab.setAttribute("hidden", "");
199+
if (this.tabs) this.tabs.setAttribute("hidden", "");
211200
}
212201
}
213202

214203
_removeNodes(list) {
215-
let host = this.isTab ? this.tab : this.accordion;
216-
217204
list.forEach(item => this._removeNode(item));
218205

219206
// Check if the container is empty
220-
if (!host.hasChildNodes()) host.setAttribute("hidden", "");
207+
[this.tabs, this.accordion].forEach(host => {
208+
if (!host.hasChildNodes()) host.setAttribute("hidden", "");
209+
});
221210
}
222211

223212
_findConnection(node, host) {
@@ -240,7 +229,7 @@ class PfeContentSet extends PFElement {
240229
}
241230

242231
_removeNode(node) {
243-
[this.tab, this.accordion].forEach(host => {
232+
[this.tabs, this.accordion].forEach(host => {
244233
const connection = _findConnection(node, host);
245234
if (connection) host.removeChild(connection);
246235
// Fire a full rebuild if it can't determine the mapped element
@@ -249,37 +238,41 @@ class PfeContentSet extends PFElement {
249238
}
250239

251240
_updateNode(node, textContent) {
252-
[this.tab, this.accordion].forEach(host => {
241+
[this.tabs, this.accordion].forEach(host => {
253242
const connection = _findConnection(node, host);
254243
if (connection) connection.textContent = textContent;
255244
// Fire a full rebuild if it can't determine the mapped element
256245
else this._build();
257246
});
258247
}
259248

260-
_buildSets(sets) {
249+
_buildSets(sets, template) {
261250
let fragment = document.createDocumentFragment();
262251

263252
for (let i = 0; i < sets.length; i = i + 2) {
264253
let header = sets[i];
265254
let panel = sets[i + 1];
266-
const template = this.displayTemplate.content.cloneNode(true);
255+
256+
// Set up the template for the sets of content
257+
const wrapper = document.createElement("template");
258+
wrapper.innerHTML = template.trim();
259+
const templateMarkup = wrapper.content.cloneNode(true);
267260

268261
if (!header) this.warn(`no element found at position ${i} of the light DOM input.`);
269262
if (!panel) this.warn(`no element found at position ${i + 1} of the light DOM input.`);
270263

271264
if (header && this._isHeader(header) && panel && this._isPanel(panel)) {
272265
// Capture the line-item from the template
273266
[header, panel].forEach((region, idx) => {
274-
const type = idx === 0 ? "header" : "panel";
267+
const section = idx === 0 ? "header" : "panel";
275268

276-
let piece = template.querySelector(`[content-type="${type}"]`).cloneNode(true);
269+
let piece = templateMarkup.querySelector(`[content-type="${section}"]`).cloneNode(true);
277270

278271
const id = region.id || region.getAttribute("pfe-id") || this.randomId;
279272
const clone = region.cloneNode(true);
280273

281274
// Remove the flag from the clone
282-
clone.removeAttribute(`${this.tag}--${type}`);
275+
clone.removeAttribute(`${this.tag}--${section}`);
283276

284277
// Append a clone of the region to the template item
285278
piece.appendChild(clone);
@@ -299,7 +292,8 @@ class PfeContentSet extends PFElement {
299292

300293
_build(addedNodes) {
301294
// Check if the appropriate tag exists already
302-
[this.tab, this.accordion].forEach(host => {
295+
[this.tabs, this.accordion].forEach(host => {
296+
const template = host.tag === "pfe-tabs" ? PfeTabs.contentTemplate : PfeAccordion.contentTemplate;
303297
// If no id is present, give it the id from the wrapper
304298
if (!host.id) host.id = this.id || this.pfeId || this.randomId;
305299

@@ -308,12 +302,10 @@ class PfeContentSet extends PFElement {
308302
// Clear out the content of the host if we're using the full child list
309303
if (!addedNodes && rawSets) host.innerHTML = "";
310304

311-
// If sets is not null, build them usin gthe template
305+
// If sets is not null, build them using the template
312306
if (rawSets) {
313-
let sets = this._buildSets(rawSets);
314-
if (sets) {
315-
host.appendChild(sets);
316-
}
307+
let sets = this._buildSets(rawSets, template);
308+
if (sets) host.appendChild(sets);
317309
}
318310

319311
this._toggleVisible();
@@ -324,8 +316,9 @@ class PfeContentSet extends PFElement {
324316
// pass the selectedIndex property down from pfe-content-set
325317
// to pfe-tabs if there is a selectedIndex value that's not 0
326318
if (this.isTab) {
319+
// Pass the selectedIndex down to the tabset
327320
if (this.selectedIndex) {
328-
this.tab.selectedIndex = this.selectedIndex;
321+
this.tabs.selectedIndex = this.selectedIndex;
329322
}
330323
}
331324
});

elements/pfe-tabs/src/pfe-tabs.js

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class PfeTabs extends PFElement {
4444
}
4545

4646
// Each set contains a header and a panel
47-
static get template() {
47+
static get contentTemplate() {
4848
return `
4949
<pfe-tab content-type="header" slot="tab"></pfe-tab>
5050
<pfe-tab-panel content-type="panel" slot="panel"></pfe-tab-panel>
@@ -68,7 +68,8 @@ class PfeTabs extends PFElement {
6868
values: ["horizontal", "vertical"]
6969
},
7070
// Do not set a default of 0, it causes a the URL history to
71-
// be updated on load for every tab
71+
// be updated on load for every tab; infinite looping goodness
72+
// Seriously, don't set a default here unless you do a rewrite
7273
selectedIndex: {
7374
title: "Index of the selected tab",
7475
type: Number,
@@ -167,15 +168,15 @@ class PfeTabs extends PFElement {
167168
}
168169

169170
connectedCallback() {
170-
super.connectedCallback();
171-
172-
this.addEventListener("keydown", this._onKeyDown);
173-
this.addEventListener("click", this._onClick);
174-
175171
Promise.all([customElements.whenDefined(PfeTab.tag), customElements.whenDefined(PfeTabPanel.tag)]).then(() => {
172+
super.connectedCallback();
173+
176174
if (this.hasLightDOM()) this._init();
177175

178176
this._observer.observe(this, TABS_MUTATION_CONFIG);
177+
178+
this.addEventListener("keydown", this._onKeyDown);
179+
this.addEventListener("click", this._onClick);
179180
});
180181
}
181182

@@ -195,6 +196,7 @@ class PfeTabs extends PFElement {
195196
}
196197

197198
_selectedIndexHandler(oldVal, newVal) {
199+
// Wait until the tab and panels are loaded
198200
Promise.all([customElements.whenDefined(PfeTab.tag), customElements.whenDefined(PfeTabPanel.tag)]).then(() => {
199201
this._linkPanels();
200202
this.selectIndex(newVal);
@@ -212,9 +214,7 @@ class PfeTabs extends PFElement {
212214
}
213215

214216
select(newTab) {
215-
if (!newTab) {
216-
return;
217-
}
217+
if (!newTab) return;
218218

219219
if (newTab.tagName.toLowerCase() !== PfeTab.tag) {
220220
this.warn(`the tab must be a ${PfeTab.tag} element`);
@@ -231,14 +231,16 @@ class PfeTabs extends PFElement {
231231
const tabs = this._allTabs();
232232
const tab = tabs[index];
233233

234-
if (!tab) {
234+
if (tabs.length > 0 && !tab) {
235235
this.warn(`tab ${_index} does not exist`);
236236
return;
237+
} else if (!tabs && !tab) {
238+
// Wait for upgrade?
239+
return;
237240
}
238-
239-
// @IE11 doesn't support URLSearchParams
240-
// https://caniuse.com/#search=urlsearchparams
241241
if (this.selected && this.tabHistory && this._updateHistory && CAN_USE_URLSEARCHPARAMS) {
242+
// @IE11 doesn't support URLSearchParams
243+
// https://caniuse.com/#search=urlsearchparams
242244
// rebuild the url
243245
const pathname = window.location.pathname;
244246
const urlParams = new URLSearchParams(window.location.search);
@@ -255,19 +257,22 @@ class PfeTabs extends PFElement {
255257

256258
_init() {
257259
const tabIndexFromURL = this._getTabIndexFromURL();
260+
this._linked = false;
261+
this._linkPanels();
262+
263+
// Force role to be set to tablist
264+
if (window.ShadyCSS) this._observer.disconnect();
265+
266+
this.role = "tablist";
258267

259268
if (tabIndexFromURL > -1) {
260269
this._setFocus = true;
261270
this.selectedIndex = tabIndexFromURL;
262-
} else if (this.selectedIndex === null) {
263-
this.selectedIndex = 0;
264271
}
265272

266-
// Force role to be set to tablist
267-
this.role = "tablist";
273+
if (!this.selectedIndex) this.selectedIndex = 0;
268274

269-
this._linked = false;
270-
this._linkPanels();
275+
if (window.ShadyCSS) this._observer.observe(this, TABS_MUTATION_CONFIG);
271276
}
272277

273278
_linkPanels() {
@@ -303,6 +308,8 @@ class PfeTabs extends PFElement {
303308
}
304309

305310
_panelForTab(tab) {
311+
if (!tab || !tab.controls) return;
312+
306313
return this.querySelector(`#${tab.controls}`);
307314
}
308315

@@ -329,9 +336,13 @@ class PfeTabs extends PFElement {
329336
}
330337

331338
_getTabIndex(_tab) {
332-
const tabs = this._allTabs();
333-
const index = tabs.findIndex(tab => tab.id === _tab.id);
334-
return index;
339+
if (_tab) {
340+
const tabs = this._allTabs();
341+
return tabs.findIndex(tab => tab.id === _tab.id);
342+
} else {
343+
this.warn(`No tab was provided to _getTabIndex; required to return the index value.`);
344+
return 0;
345+
}
335346
}
336347

337348
reset() {
@@ -343,6 +354,8 @@ class PfeTabs extends PFElement {
343354
}
344355

345356
_selectTab(newTab) {
357+
if (!newTab) return;
358+
346359
this.reset();
347360

348361
const newPanel = this._panelForTab(newTab);
@@ -419,8 +432,12 @@ class PfeTabs extends PFElement {
419432

420433
event.preventDefault();
421434

422-
this.selectedIndex = this._getTabIndex(newTab) || 0;
423-
this._setFocus = true;
435+
if (newTab) {
436+
this.selectedIndex = this._getTabIndex(newTab);
437+
this._setFocus = true;
438+
} else {
439+
this.warn(`No new tab could be found.`);
440+
}
424441
}
425442

426443
_onClick(event) {
@@ -431,12 +448,11 @@ class PfeTabs extends PFElement {
431448
if (!foundTab) return;
432449

433450
// Update the selected index to the clicked tab
434-
this.selectedIndex = this._getTabIndex(event.currentTarget) || 0;
451+
this.selectedIndex = this._getTabIndex(event.currentTarget);
435452
}
436453

437454
_getTabIndexFromURL() {
438455
let urlParams;
439-
let tabIndex = -1;
440456

441457
// @IE11 doesn't support URLSearchParams
442458
// https://caniuse.com/#search=urlsearchparams
@@ -453,11 +469,11 @@ class PfeTabs extends PFElement {
453469

454470
if (urlParams && tabsetInUrl) {
455471
let id = urlParams.get(`${this.id}`) || urlParams.get(`pfe-${this.id}`); // remove this condition when it's no longer used in production
456-
tabIndex = this._allTabs().findIndex(tab => tab.id === id);
472+
return this._allTabs().findIndex(tab => tab.id === id);
457473
}
458474
}
459475

460-
return tabIndex;
476+
return -1;
461477
}
462478

463479
_popstateEventHandler() {

0 commit comments

Comments
 (0)