question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Tabs don't update when array order changes

See original GitHub issue

Describe the bug

<b-tabs> doesn’t update reliably when the array changes.

  • If the number of elements changes, the update seems to work.
  • If the order of elements changes, it doesn’t seem to update.

#1781 is (almost) a duplicate of this. In that issue, the user used a

<b-tab v-for="tab in tabs" :title="tab.title" :key="`key-${tab.id}`">

The bug was closed when @emanuelmutschlechner says:

You must use the index of tabs array. By using the id as key, shuffling the tabs array will not change the underlying HTML at all.

As in:

<b-tab v-for="(tab, index) in tabs" :title="tab.title" :key="`key-${index}`">

I think that reasoning is wrong. Forcing me to use index as key means that something is broken.

Superficially it seems to work. But as the Vue documentation points out:

This default mode is efficient, but only suitable when your list render output does not rely on child component state or temporary DOM state (e.g. form input values).

(highlight theirs)

So if the different tabs have e.g. <input>s then Vue will get confused. That is exactly what key is for. If you use index as key, you might as well omit it altogether as using the index is the default behavior

The Vue documentation explicitly uses item.id in several places. I don’t find any index used for key anywhere.

And using :key="item.id", <b-tabs> doesn’t update when the sequence changes.

In my opinion, there is a bug here. :key="item.id" should work.

Steps to reproduce the bug

See this codepen. It has inputs on the tabs and you can see that the inputs end up in the wrong tabs when the array order changes.

Expected behavior

I expect:

<b-tab v-for="tab in tabs" :title="tab.title" :key="`key-${tab.id}`">

to work whenever tabs changes - also if just the order changes.

Versions

Libraries:

  • BootstrapVue: 2.0.0-rc.22
  • Bootstrap: 4.3.1
  • Vue: 2.6.10

Demo link

See this codepen

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:27 (18 by maintainers)

github_iconTop GitHub Comments

1reaction
pmorchcommented, Jun 17, 2019

@tmorehouse: I just built dev from the current git repo and hosted it myself somewhere and it seems to work now. What made it work was commit 130f8ffe85305a4f6eb9f38e199562edeabf72ea.

I now get it.

<b-tabs> is letting Vue do the ordering of the <b-tab> instances that contain the tab content in the default slot. And they’re ordered correctly because of the key on <b-tab>. But BootstrapVue isn’t involved with any of that. In tabs.js, this.getTabs() aligns the order of the buttons with DOM order of tabs previously set up by Vue in the default slot.

What I was struggling with was that searching for key in src/components/tabs/* turned up so precious little, as I was assuming (erroneously), that somehow the key attribute needed to be passed on somewhere. So I was thinking “the key attribute I supply isn’t consumed/handled anywhere”. But no. default slot and Vue takes care of all that perfectly. Once that is done, BTabs/tabs.js just mirrors the DOM order in getTabs().

The fact that the order of buttons was wrong led me to believe that the key attribute “wasn’t working”. What I now understand is that the key attribute the entire time correctly determined the order inside .tab-content, but that the ul.nav-tabs didn’t reliably mirror that (correct) DOM ordering.

And so now with 130f8ffe85305a4f6eb9f38e199562edeabf72ea it (looks like) it observes/watches this.$refs.tabsContainer and calls this.updateTabs.bind(this) when that changes. (Essentially the same fix as @emanuelmutschlechner put in manually.)

My faith in the universe is restored.

I hope I have not done irreparable damage here. I apologize for being too stubborn and just generally a pain the behind. I agree it looks like this will be fixed in 2.0.0-rc.24.

0reactions
tmorehousecommented, Jun 17, 2019

BootstrapVue 2.0.0-rc.24 has been published about an hour ago: https://www.npmjs.com/package/bootstrap-vue

Read more comments on GitHub >

github_iconTop Results From Across the Web

Angular: ngFor not updating the view when the objects of ...
I am constantly changing the array of objects to show or hide tabs. But some tabs are staying active, because I think the...
Read more >
UI not updated when array is changed - help? : r/angular
The new data items are successfully retrieved and added to the array, but the UI does not update. If I carry out another...
Read more >
SwiftUI - List view doesn't get updated even the state gets ...
If a new order is created and when I append it, it gets updated. If an order is completed, and when I remove...
Read more >
Using IndexedDB - Web APIs - MDN Web Docs
IndexedDB is a way for you to persistently store data inside a user's browser. Because it lets you create web applications with rich...
Read more >
Use Excel with earlier versions of Excel - Microsoft Support
You can then make the necessary changes to avoid the loss of data or ... you cannot manually turn on Compatibility Mode in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found