designing personalized tabs in angular material

Can anyone offer suggestions on how to create custom tabs, like the ones shown in the example image below? For instance, having tabs for general information, security roles, SSO, password, and login. Clicking on each tab would display relevant information on the right side of the screen. Is there a way to make it scroll smoothly to show the selected card at the top position? Any tips or ideas on how to achieve this effect? Thank you.

Link to Example

https://i.sstatic.net/DA5gk.png

Answer №1

It's all about having fun with the [fxFlexOrder] feature

If you create an array like this:

order=[0,1,2]

each fxFlex element can be handled as follows:

//use order[0] and sortOrder(0) for the first item
//    order[1] and sortOrder(1) for the second one
//    ...
<div fxFlex [fxFlexOrder]="order[0]" (click)="sortOrder(0)">
..
</div>

The sortOrder function modifies the array and scrolls to the top of the window

  sortOrder(index) {
    const value=this.order[index]
    if (value != 0) {
      this.order = this.order.map(
        (x, i) => (x = i == index ? 0 : x < value ? x + 1 : x)
      );
      window.scrollTo(0, 0);
    }
  }

Your modified code on StackBlitz showcasing these changes

Answer №2

There is an alternative approach that does not use mat-flex, but instead uses a div with position absolute and manual animation.

Consider the following HTML structure:

<div class="container">
    <div class="column">
        <mat-card class="custom">
            {{order|json}}
        </mat-card>
    </div>
    <div class="column">
        <div #card (click)="sortOrder(0)">
            <mat-card class="custom2">
                custom 0
            </mat-card>
        </div>
        <div #card (click)="sortOrder(1)">
            <mat-card class="custom2">
                custom 1
            </mat-card>
        </div>
        <div #card (click)="sortOrder(2)">
            <mat-card class="custom2">
                custom 2
            </mat-card>
        </div>
    </div>
</div>

Using the following CSS styles:

.container{
  display:flex;
}
.column{
  margin-left:15px;
}
.column>div
{
  position:absolute;
}

The concept involves creating a manual animation. To achieve this, we use @ViewChildren to select the "cards" and inject the AnimationBuilder in the constructor.

  timing = '500ms ease-in-out';
  initPos=0;
  @ViewChildren('card', { read: ElementRef }) items: QueryList<ElementRef>;
  private player: AnimationPlayer;
  constructor(private builder: AnimationBuilder) {}

The "animate" function takes a nativeElement and a top position as parameters to create an animation for moving the element. An additional parameter "last" can be used to perform an action when the animation finishes.

  animate(element: any, top: string | number,last:boolean) {
    const myAnimation = this.builder.build([
      animate(this.timing, style({ top: top}))
    ]);
    this.player = myAnimation.create(element);
    if (last)
    {
      this.player.onDone(()=>{
        window.scrollTo(0, 0);
      })
    }
    this.player.play();
  }

The main task is to calculate the position "top" based on an array order that changes upon clicking.

  sortOrder(index: number) {
    const value = this.order[index];
    if (value != 0) {
      this.order = this.order.map(
        (x, i) => (x = i == index ? 0 : x < value ? x + 1 : x)
      );
      
    }
    let pos = this.initPos ||0;
    for (let i=0;i<this.order.length;i++)
    {
      const index=this.order.findIndex(x=>x==i);
      const card = this.items.find((_, j) => j == index);
      if (card) {
        this.animate(card.nativeElement, pos ? pos + 'px' : 0,i==this.order.length-1);
        pos += card.nativeElement.getBoundingClientRect().height;
      }

    }
  }

Lastly, remember to call the sortOrder function in ngAfterViewInit.

  ngAfterViewInit()
  {
    this.initPos=this.items.first.nativeElement.getBoundingClientRect().top;
    this.sortOrder(0)
  }

Here is the link to the StackBlitz demo

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

Linking enumeration value to an Angular material table

Is it possible to associate enum values with an Angular Material table? For instance, I have defined an enum: export enum EnumName { val1 = 1, val2 = 2, val3 = 3 } and I want the Angular Material table to display it like this: Id EnumNameColumn ...

Error: Incorrect Path for Dynamic Import

Recently, I've been trying to dynamically load locale files based on the locale code provided by Next.js. Unfortunately, every time I attempt a dynamic import, an error surfaces and it seems like the import path is incorrect: Unable to load translatio ...

Tips for compressing files on an Angular 8 production build

Our goal is to enhance the speed and performance of a website that was created using Angular 8. Seeking advice on how to compress (using gzip or brotli) angular files during production build. ...

AngularJS: The 'myInputName' property is not defined and cannot be read

Encountering an error with AngularJS: https://i.sstatic.net/TBHem.png The issue is related to the titleInput TextBox name property: @Html.TextBox("titleInput", null, new { @placeholder = @T("Message title"), @class = "form-control", ng_model = "feed.fee ...

Library for Typescript on npm

My project involves a collection of base classes in TypeScript. Within a web application built with React and written in TypeScript, I am looking to integrate a library called 'Plain Old TypeScript objects', which defines all the data types. Let& ...

Can you explain the significance of the "@" symbol prefix found in npm package names?

While reading through the Angular Component Router documentation, I came across an npm command that caught my attention: npm install @angular/router --save I'm puzzled by the meaning of @angular/router. Is this entire string a package name? If so, ...

Who is responsible for the addition of this wrapper to my code?

Issue with Sourcemaps in Angular 2 TypeScript App Currently, I am working on an Angular 2 app using TypeScript, and deploying it with the help of SystemJS and Gulp. The problem arises when I try to incorporate sourcemaps. When I use inline sourcemaps, eve ...

Using Angular 5 for sending HTTP POST requests with x-www-form-urlencoded content-type

Currently, I have been immersing myself in Angular and am nearing completion of my initial end-to-end application. This specific app is designed to interact with Spotify's public API in order to search for music and play track previews. The primary i ...

Setting up systemjs.config.js for utilizing relative paths within IIS - A step-by-step guide

My new ASP.NET MVC web application utilizes Angular for its UI components. I have set up the necessary config files in my project (e.g. package.json and systemjs.config.js). Created a test page Index.cshtml to test out the template in app.component.ts. The ...

Must run the angular code in a sequential order

I need to run the code in a specific order; first the foreach loop should be executed, followed by a call to the getHistory() method. Your assistance is greatly appreciated. const execute = async()=>{ await this.currentContent.forEach(async ...

Top method for extracting a correlation matrix using an API endpoint

I am currently storing correlations on Google Firebase in a structure that resembles the following: {a: {a: 1.0, b: 0.6, c: -0.3, ...}, b: {a: 0.6, b: 1.0, c: -0.5, ...}, ...} My goal is to efficiently retrieve a complete correlation matrix while also hav ...

Sortable layouts and tables in Ionic 3

I found a great example of an Ionic table that I'm using as reference: https://codepen.io/anon/pen/pjzKMZ <ion-content> <div class="row header"> <div class="col">Utility Company Name</div> <div c ...

Guide on assigning json array values to multiple accordion forms in Angular 6

Utilizing multiple accordion forms on the same page poses a challenge. When the Add button is clicked, an additional accordion form is added to the page. Upon submitting the second form, a set of JSON data is submitted. The resulting JSON array after three ...

Discrepancies in ESLint outcomes during React app development

As a newcomer to React development, I am encountering discrepancies between the errors and warnings identified in my project's development environment versus its production environment. Strangely, I have not configured any differences between these en ...

Angular 6: Addressing the 'ExpressionChangedAfterItHasBeenCheckedError' in dynamic form validation with reactive form by adding and removing elements

When utilizing Angular 6 Reactive Form and dynamically adding and removing new validators, an error occurs: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'disabled: false'. Current ...

Remove the service-created component instance once it has served its purpose

Can you help me troubleshoot an issue with component lifecycle in a dynamic component creation service? I have noticed that the ngOnDestroy lifecycle hook is not being called for the components. Here is a snippet of my service file code: @Injectable() ex ...

The functionality of Javascript Array.splice suddenly malfunctioned in my Angular application

While working on a project in Angular 4, I encountered a situation where I needed to batch through an array of ids. I would send the removed items to an Observable function, and upon the subscription returning, I would check the remaining array before loop ...

Node.js: The choice between returning the original Promise or creating a new Promise instance

Currently, I am in the process of refactoring a codebase that heavily relies on Promises. One approach I am considering is replacing the new Promise declaration with simply returning the initial Promise instead. However, I want to ensure that I am correctl ...

Error message pops up in WebStorm when attempting to access the map object in Angular

Within one of the services in my Angular application, I have utilized the map() function to retrieve data from the GitHub API. getUser(username: string) { // Regular Expression used for String Manipulation return this.http.get('https://api.github.com ...

Struggling to implement the proper authentication method with API in Ionic

Having an API for the login, but being new to Ionic is causing difficulty in creating the correct method for the login process. The service file is located here: providers/restapi/restapi.ts import { HttpClient } from '@angular/common/http'; im ...