Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Tab initial selection #747

Closed
bsr203 opened this issue Aug 2, 2013 · 2 comments
Closed

Tab initial selection #747

bsr203 opened this issue Aug 2, 2013 · 2 comments

Comments

@bsr203
Copy link

bsr203 commented Aug 2, 2013

Please find the plnkr

http://plnkr.co/edit/RCVFji2Upl4VRAoiAcZE?p=preview

I do my setting as (all static tabs)

 $scope.tabsettings = {
    a: {},
    b: {active: true}
  };

But, something overrides it, and the first tab become selected by default.

@pkozlowski-opensource
Copy link
Member

@ajoslin I think I've fixed most of the bugs for 0.5.0 and just want to review datepicker changes before cutting the release. Would be awesome if you could have a look at this one - I had a quick look and it is still reproducible with the latest master.

@raykin
Copy link

raykin commented Aug 12, 2013

@bsr203 I also got the same problem in my project. And I fix it locally. Please check the diff of https://github.com/raykin/bootstrap/commit/97f6f64163a7e93120adba198f80fd882f29ac6d and update your local code.
The reason of this bug is twice loop of nested watch which always set the active of first tab as true and others as false

         scope.$parent.$watch(getActive, function updateActive(value) {
            scope.active = !!value;
          });
        scope.$watch('active', function(active) {
          setActive(scope.$parent, active);
          if (active) {
             // ....

the above watch are triggered by

       tabsetCtrl.addTab(scope, true);
        // it finally trigger
       angular.forEach(tabs, function(tab) {
         tab.active = false;
       });

my fix is add a check to stop the trigger when compile the tab directive.
but it's not a perfect fix, it requires explicitly set active tab, or you will got a non selected tabset when page init rendered.
Also I run the test suits, only one test which mentioned above failed. So @bsr203 you can use the fix at now without worry about other breaks.

chrisirhc added a commit to chrisirhc/angular-ui-bootstrap that referenced this issue Aug 17, 2013
- Avoid re-initializing `tab.active`
- `setActive` only when all `tab.active` are set up (on the next
  digest cycle)

Before I go to explain, there are up to two expressions that indicate
whether a tab is active:

  1. `active` variable in the isolate scope of the tab directive
  2. The expression from the active attribute (`attrs.active`) if it
     is set, I'll call this `getActive`, as that's the variable that
     refers to it.

During initial linking (adding of tabs), the `active` variable in the
tab's isolate scope tracks the active tab. When the first tab is
added, it's `active` is set to true since there's no way to know if
subsequent tabs are active since they haven't been added yet. As such,
at this point, it is not meaningful to set assign the `getActive`
with the value of `active`. At least not until all the tabs have been
added. Hence, a good time would be to wait until the next $digest
cycle.

A watcher is called asynchronously after initialization even if there
is no change on the expression's value.

As such, we can leave that to the watcher for the `active` expression
to initialize getActive by calling setActive during its initlization
cycle.

However, there is a chance (if the $digest cycles and planets
align...) that the `active` variable gets initialized a second time
using the `getActive` (in the watcher for `getActive`). Since we're
already setting `active` to `getActive`, and the `active` variable
should now be carrying the *truth*. Avoid this re-initialization.

---

This fix is ugly because the logic for the two-way binding of `active`
and the `getActive` is complex. Consider refactoring the
implementation for maintaining the two-way binding (see ngModel for
inspiration).

Fixes angular-ui#747.
@ajoslin ajoslin closed this as completed Sep 23, 2013
ajoslin pushed a commit that referenced this issue Sep 23, 2013
Closes #834, Fixes #747

- Avoid re-initializing `tab.active`
- `setActive` only when all `tab.active` are set up (on the next
  digest cycle)

Before I go to explain, there are up to two expressions that indicate
whether a tab is active:

  1. `active` variable in the isolate scope of the tab directive
  2. The expression from the active attribute (`attrs.active`) if it
     is set, I'll call this `getActive`, as that's the variable that
     refers to it.

During initial linking (adding of tabs), the `active` variable in the
tab's isolate scope tracks the active tab. When the first tab is
added, it's `active` is set to true since there's no way to know if
subsequent tabs are active since they haven't been added yet. As such,
at this point, it is not meaningful to set assign the `getActive`
with the value of `active`. At least not until all the tabs have been
added. Hence, a good time would be to wait until the next $digest
cycle.

A watcher is called asynchronously after initialization even if there
is no change on the expression's value.

As such, we can leave that to the watcher for the `active` expression
to initialize getActive by calling setActive during its initlization
cycle.

However, there is a chance (if the $digest cycles and planets
align...) that the `active` variable gets initialized a second time
using the `getActive` (in the watcher for `getActive`). Since we're
already setting `active` to `getActive`, and the `active` variable
should now be carrying the *truth*. Avoid this re-initialization.
codedogfish pushed a commit to codedogfish/angular-ui-bootstrap that referenced this issue Sep 15, 2015
Watch the allowClear attribute for changes
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants