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.

(tabset, feature): Ability to control active tab via activeId or some @Input property

See original GitHub issue

Feature description:

Currently, to change active tab programmatically we have to call NgbTabset’s select() method. activeId property does not work for this purpose.

This causes issues in certain scenarios. For example, in a “truly” reactive app, we have to not only manually subscribe() to update the active tab instead of using data binding, we also have to call select() on the next JS event cycle (see the demo below). I’m not sure about the latter, but the former makes API not very reactive and Angular-friendly.

Also, we have to write extra code in a component (and in some cases in a template as well) just to get access to NgbTabset instance like this:

  @ViewChild(NgbTabset)
  private tabset: NgbTabset;

Conversely, Material MatTabGroup has this feature (selectedIndex property) and could be a good example here.

Link to minimally-working plunker that reproduces the issue:

Stackblitz

Version of Angular, ng-bootstrap, and Bootstrap:

Angular: 6.0.2

ng-bootstrap: 2.0.0

Bootstrap: 4.1.1

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:21 (9 by maintainers)

github_iconTop GitHub Comments

2reactions
benouatcommented, Jun 20, 2018

You can actually achieve what you want to do in a much more simple way 👍

Here is a stackblitz: https://ng-bootstrap-tabset-reactive-tab-select-phepks.stackblitz.io

There is no need here to use changeDetectorRef, nor applicationRef. You just need to do 3 things (step 2 is not even an action!) :

  1. Make sure to create the proper data structure associated to the tab you want to generate
  2. Wait for changeDetection to be executed, so that the ngFor on the tabset is executed.
  3. Select the proper tab

In order to properly achieve the transition from step 2 to step 3 you need to execute the this.tabset.select( ... ) after the changeDetection. To do that, you could:

  • Use setTimeout(... , 0) which basically will execute the callback beginning of next tick
  • Use zone.onStable that hooks itself at the end of the microtask execution, ie. just before going to next tick.

Personally I would rather prefer the second one using zone as it is much clearer to me as compare to the magical fallback of setTimeout. It’s definitely more Angular oriented, hence more verbose also…

2reactions
pkozlowski-opensourcecommented, Jun 15, 2018

Using data binding for this types of APIs has one fundamental issue in Angular - it doesn’t allow you to select the same tab twice. Let me explain the scenario:

  • data binding for activeId changes to, say tab-1;
  • user clicks on another tab (so now active tab is, say tab-3;
  • you want to select tab-1 again - BAM - it doesn’t work since Angular change detection works on binding level and for Angular value of activeId didn’t change (internal model derived from activeId changed but not the activeId binding itself!

We could use 2-way binding ([(activeId)]="exp" but it would have following drawbacks:

  • one couldn’t use “static” values (ex. atvieId="my-tab";
  • users would be getting wired errors when not using 2-way data binding (ex. [activeId]="exp")

Explicit methods like select(...) is the only way I know to solve it elegantly. Happy to discuss other options / other API ideas, if you’ve got suggestions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Angular Bootstrap Tabs Set Active Tab Through Markup
For some reason when I set the active attribute on a tab it seems to mangle the state of the tabs. The page...
Read more >
Create a tabset panel — tabsetPanel - R Shiny
Use type = "hidden" in conjunction with tabPanelBody() and updateTabsetPanel() to control the active tab via other input controls. (See example below).
Read more >
Tabs | Components - BootstrapVue
Create a widget of tabbable panes of local content. The tabs component is built upon navs and cards internally, and provides full keyboard...
Read more >
tabsetPanel could use an active= parameter to specify the tab ...
I generate tabsets in a reactive function, and I want to make sure the selected tab doesn't change each time the reactive UI...
Read more >
JavaScript · Bootstrap 3.3.6 Documentation - BootstrapDocs
This provides the ability to stop the execution of an action before it starts. ... nav-tabs" role="tablist"> <li role="presentation" class="active"><a ...
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