material-components-web icon indicating copy to clipboard operation
material-components-web copied to clipboard

Can't switch between dynamically created tabs in MDCTabBar.

Open vedtam opened this issue 6 years ago • 5 comments

Hi guys,

In my element I'm displaying category titles as Tabs. The problem is that I can't switch between tabs which are rendered after the categories get fetched:

...
    <div class="mdc-tab-bar" role="tablist">
        <div class="mdc-tab-scroller">
          <div class="mdc-tab-scroller__scroll-area">
            <div class="mdc-tab-scroller__scroll-content">
              
              <button class="mdc-tab mdc-tab--active" 
                      role="tab" tabindex="0" aria-selected="true">
                <span class="mdc-tab__content">
                  <!-- <span class="mdc-tab__icon material-icons">favorite</span> -->
                  <span class="mdc-tab__text-label">VIEW ALL</span>
                </span>
                <span class="mdc-tab-indicator mdc-tab-indicator--active">
                  <span class="mdc-tab-indicator__content mdc-tab-indicator__content--underline"></span>
                </span>
                <span class="mdc-tab__ripple"></span>
              </button>

              ${Object.values(categories || []).map((category) => html`
                <button class="mdc-tab" 
                        role="tab" tabindex="0" aria-selected="false">
                  <span class="mdc-tab__content">
                    <!-- <span class="mdc-tab__icon material-icons">favorite</span> -->
                    <span class="mdc-tab__text-label">${category}</span>
                  </span>
                  <span class="mdc-tab-indicator">
                    <span class="mdc-tab-indicator__content mdc-tab-indicator__content--underline"></span>
                  </span>
                  <span class="mdc-tab__ripple"></span>
                </button>
              `)}

            </div>
          </div>
        </div>
      </div>
  `;
  }

...

stateChanged(state: RootState) {
  this.categories = state.category.items;
}

firstUpdated(){
   new MDCTabBar(this.shadowRoot.querySelector('.mdc-tab-bar'));
}

I've created a demo on glitch that demonstrates the issue, you can see the source here.

I've tried to look for answers on discord, but I got no proper answer there. Thanks!

vedtam avatar Dec 28 '18 12:12 vedtam

Reproduction with vanilla MDC Web: https://glitch.com/edit/#!/mdc-web-4214

We're only ever instantiating tabs based on the DOM during initialize. We would probably need to add an explicit addTab (and removeTab?) API that would receive an mdc-tab element (or possibly an index for removal), or something like reinstantiateTabs that would destroy all current tab instances and reinstantiate based on the current state of the DOM.

kfranqueiro avatar Jan 04 '19 20:01 kfranqueiro

@kfranqueiro thanks for the clarification. Well as a workaround, I moved the 'static' tab inside the loop that generates the rest of the tabs after data gets fetched, now all tabs render simultaneously but I can see other cases where this wouldn't be an option so having an add/remove Tab or reinstantiateTabs method would be nice.

vedtam avatar Jan 07 '19 10:01 vedtam

I think you might forget to import those files

import {MDCTabBar} from '@material/tab-bar'; const tabBar = new MDCTabBar(document.querySelector('.mdc-tab-bar'));

Rajeshbhartia avatar Feb 18 '20 06:02 Rajeshbhartia

Is there any update on this.

It seems a lot of the mdc controls require that the data be statically passed to any implementation. It makes the controls rather unsuitable to use.

To work around this, I had to catch my tab-item render event, and hack the MDC tab into the tabList of the tabAdapter.

On top of this, there seems to be a global tracking of these tab items, so each tab-item must have a unique id globally.

  const anyTabBar = this.TabBar as any;

  anyTabBar.tabList.push(Tab);

  const randomId = Math.round(Math.random() * Number.MAX_VALUE);

  const id = `mdc-tab-${ randomId }`;

  Tab.id = id;

  Tab.root.id = id;

KrisSodroski avatar May 24 '22 15:05 KrisSodroski

I am also interested in some kind of add/remove Tab or reinstantiateTabs solution.

JoshMayberry avatar Aug 15 '22 17:08 JoshMayberry