Angular - Dynamic Tabs with Collapsible Dropdowns

Currently, I have a code snippet that hides and moves tabs into a dropdown menu based on the available width. Everything has been working smoothly so far. However, now the user wants to be able to open the Dropdown Menu (if there is an Active Tab inside) to display the currently selected tab.

Here's the link to the code

I am looking to exclude the Active Tab from being hidden and position it right before the Dropdown Menu Toggle ("More") so that the user can easily see which tab is selected. The screenshots provided below should give you a better idea of what I'm aiming for:

Screenshot 1 -> Screenshot 2

I have attempted to exclude the Active Tab from the "hiddenItems" array within my "primaryItems.forEach()" method without success. Would using the "Array.splice()" method be a valid approach in this scenario?

Thank you in advance!

Answer №1

Hey there! After reviewing your code, I found that solving the issue using @HostListeners was challenging due to recent updates in listening for changes. However, there are alternative solutions that can be just as effective, if not more so, especially when aiming for a cleaner approach. When you modify the hidden status of your elements, your application may forget their previous state. By implementing listeners to detect these changes, your app can re-render tab components accordingly. This process ensures that displayed components are gathered and hidden again to maintain consistency.

Now, let me provide you with a solution:

To maintain up-to-date data sets, we need to introduce new variables like this:

...
  resizeTimeout: number; 
 
  displayed_data: number[] = [];
  dataOfHiddens: number[] = [];
...

After executing the renderTabs function, remember to include the following lines to preserve the latest information:

...

    this.activeIndexIsHidden = hiddenItems.includes(this.activeIndex);
    this.dataOfHiddens = hiddenItems;
    this.displayed_data = displayedItems;
  }
}

Use displayedItems to keep track of updates efficiently.

const hiddenItems: number[] = [];
const displayedItems: number[] = [];

When iterating through primary items, adjust their behavior dynamically based on specific conditions. This filtering method allows you to control how each item behaves within the frame:

primaryItems.forEach((item: HTMLElement, index: number) => {

 // Check if active index is hidden
  if (this.dataOfHiddens.includes(this.activeIndex)) {
    // Find the highest index among visible tabs and hide those exceeding it
    let ind = Math.max(...this.displayed_data);
    if (index >= ind && this.activeIndex != index) {
      item.classList.add('tabs__item--hidden');
      item.querySelector('button').setAttribute('disabled', 'true');
      hiddenItems.push(index);
    }
  } else if (this.dataOfHiddens.includes(index) && index != this.activeIndex) {
    item.classList.add('tabs__item--hidden');
    item.querySelector('button').setAttribute('disabled', 'true');
    hiddenItems.push(index);
  } else if (primaryWidth - safetyOffset >= stopWidth + item.offsetWidth + flexGap) {
    stopWidth += item.offsetWidth + flexGap;
    displayedItems.push(index);
  } else {
    if (this.activeIndex != index) {
      item.classList.add('tabs__item--hidden');
      item.querySelector('button').setAttribute('disabled', 'true');
      hiddenItems.push(index);
    }
  }
});

Ensure to review additional aspects for optimal performance. This solution has been tested and proven to work effectively. Feel free to ask any questions by leaving a comment below.

Answer №2

I managed to resolve the issue by substituting the "More" Text with the Selected Tab Text, as long as the Active Tab (Index) is among the hiddenItems. If not, the default "More" Text will be displayed.

Although this may not be exactly what I had in mind initially, it seems to be the simplest and most efficient solution for now.

Link to the solution on StackBlitz

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for concealing the delete button within the main content area and displaying it in the subsequent "add" pop-up window upon clicking the "add" button in Angular

I have a card with add and delete buttons. I want only the add button to show initially, and when clicked, a new card should open with both add and delete buttons. Everything is working as expected except I can't figure out how to hide the delete butt ...

"Encountering an undefined Angular object after making an HTTP request

I've encountered a challenge that seems straightforward to most, but after investing substantial time in it, I've come to the realization that I need some assistance. As part of my project on frontendmentor.io, I'm facing a roadblock with o ...

Using Angular2 rc3 to inject router into unit tests

After the transition to Angular2 rc3, I've encountered issues with tests that require the Router injection. Previously, I relied on the ROUTER_FAKE_PROVIDERS from the router/testing file, but it appears that it is no longer available. Can anyone offer ...

The attribute 'nodeQuery' is not found within the type '{}'

While working on a project with Angular and Apollo, I encountered an issue when trying to build the application using ng build. Despite functioning correctly on localhost:4200, I faced errors during the build process. The app communicates with a GraphQL se ...

I encountered an issue while trying to implement a custom pipe using the built-in pipe

My custom pipe seems to be functioning well, except for the built-in pipes not working within it. I've imported Pipe and can't figure out what could be causing the issue. Below is the code with the errors: import { Pipe, PipeTransform } from &a ...

I have a question about an error message I received: The module 'DashboardModule' imported an unexpected directive 'BarChartComponent'. It is asking for a @NgModule annotation to be added

I'm encountering a compilation error with the code: 'BarChartComponent' imported by the module 'DashboardModule' is causing an unexpected directive error. Please make sure to include a @NgModule annotation. dashboard.modul ...

Displaying a webpage with search results generated by a PHP multidimensional array

I am dealing with a complex array structure that I received as a response from an API for bus ticket booking service. The array represents search results for buses available for a specific source and destination. The array contains information about each ...

Ionic causing delay in updating ngModel value in Angular 2

My ion-searchbar is set up like this: <ion-searchbar [(ngModel)]="searchQuery" (keyup.enter)="search();"></ion-searchbar> In the typescript file, the searchQuery variable is defined as follows: export class SearchPage { searchQuery: string ...

Querying MongoDB for a field within an embedded document in an array

In my document, stock prices are stored in an embedded array within MongoDB. I am looking to retrieve a specific stock price based on the date and then display it in the template for further calculations. You can find an example in this Meteorpad. The hel ...

Converting Antdesign's Datepicker to Typescript

I'm having trouble figuring out how to properly annotate the dateObj parameter in the handleDateChange function that I've created. App.tsx import { useState } from 'react'; import logo from './logo.svg'; ...

When Typescript compiles to JavaScript, it may result in code that appears to be a function

In the following typescript code snippet: export enum UID { FACTORY, ROBOT } we see how it compiles to javascript: (function (UID) { UID._map = []; UID._map[0] = "FACTORY"; UID.FACTORY = 0; UID._map[1] = "ROBOT" ...

Changing the height of the parent div in Angular 2 to match the height of the child div that holds an image

When I make an HTTP call to fetch a block of HTML from an external source, the structure of the retrieved HTML looks like this: <div class="container"> <div class="wrapper"> <div class="image"> <img src="img_url> ...

Error in Typescript: Array containing numbers is missing index property `0`

This is the code for my class: class Point{ coordinates: [number, number, number]; constructor(coordinates: [string, string, string]) { this.coordinates = coordinates.map((coordinate) => { return Math.round(parseFloat(coordinate) *100)/ ...

Python: finding the dot product of columns in matrices

I am interested in calculating the dot-product between the first column of a 2D array (size n x k) and all columns of another 2D array with the same dimensions. I want to repeat this process for all columns of the first array and store the results in a t ...

What is the process for upgrading TypeScript to the latest version?

Is there a way to upgrade TypeScript version for ASP.net MV5 project in Visual Studio 2015? I attempted searching through Nuget but couldn't locate it. There seems to be an issue with the razor intellisense (index.d.ts file) and I'm hoping that ...

Steps to avoid reinitializing the component upon changing routes in an Angular 9 component

In my component, the width of a chart is stored in a variable (because I can't use style for d3). However, every time the route changes, all variables in this class component become undefined. I have tried using ngIf, services (which also become unde ...

Angular 6 provides a regular expression that specifically targets the removal of any characters that are not numbers and enforces the allowance of

I have tried various solutions to restrict input in an Angular material input box, but none seem to be effective for my specific case. I need the input field to only allow numbers and a decimal point. Any other characters should be automatically removed as ...

Is there a way to access FormArray within a formGroup nested inside another formGroup?

I have a set of data structured like this: [ { id: "1", name: "task1", taskForms: [ { id: "8782", name: "ProcedureComment", sortOrder: null, descr ...

Guide for configuring a server to exclusively render Vue components

I have been utilizing the vue-no-ssr library (available at https://github.com/egoist/vue-no-ssr), but it only renders components on the client side. I require my component to render on the server side. Is there a method to create a vue component that exclu ...

SlidingPane header in React disappearing behind Nav bar

Here is the code snippet from my App.js file: export class App extends React.Component { render() { return ( <BrowserRouter> <NavigationBar /> <Routes /> </BrowserRout ...