(tabset, feature): Ability to control active tab via activeId or some @Input property
See original GitHub issueFeature 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:
Version of Angular, ng-bootstrap, and Bootstrap:
Angular: 6.0.2
ng-bootstrap: 2.0.0
Bootstrap: 4.1.1
Issue Analytics
- State:
- Created 5 years ago
- Comments:21 (9 by maintainers)
Top GitHub Comments
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
, norapplicationRef
. You just need to do 3 things (step 2 is not even an action!) :ngFor
on the tabset is executed.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:setTimeout(... , 0)
which basically will execute the callback beginning of next tickzone.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 ofsetTimeout
. It’s definitely more Angular oriented, hence more verbose also…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:
activeId
changes to, saytab-1
;tab-3
;tab-1
again - BAM - it doesn’t work since Angular change detection works on binding level and for Angular value ofactiveId
didn’t change (internal model derived fromactiveId
changed but not theactiveId
binding itself!We could use 2-way binding (
[(activeId)]="exp"
but it would have following drawbacks:atvieId="my-tab"
;[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.