Changing the color of a specific span using Angular

I am working with a dynamic mat-table where columns are added and populated on the fly. The table headers are styled using divs and spans. My goal is to change the color of a header to black when clicked, but also un-toggle any previously selected header.

At the moment, I have managed to toggle a header's color, but I am struggling with untoggling another header. Initially, all the spans were being toggled at once, but I was able to fix this by toggling based on each span's ID.

Below is a snippet of the HTML code I have implemented:

<table mat-table [dataSource]="dataSource">
      <ng-container matColumnDef="{{column.columnName1}}" *ngFor = "let column of displayColumns">
          <th mat-header-cell *matHeaderCellDef>
            <div *ngIf = "column.stackedHeader">
              <div [ngStyle] = "{'color': (column.toggled) ? 'black' : 'grey'}" (click) = "toggleColumn($event)" class = "column-header" id = "{{column.columnName1}}">
                {{ column.columnHeader1 }}
              </div>
              <div (click) = "toggleColumn($event)" class = "column-header" id = "{{column.columnName2}}">
                {{ column.columnHeader2 }}
              </div>
            </div>
            <div *ngIf = "!column.stackedHeader" (click) = "toggleLocationColumn($event)" class = "column-header" id = "{{column.columnName1}}">
              {{column.columnHeader1}}
            </div>
          </th>
toggleColumn($event) {
    const columnId = $event.toElement.id;
    this.columnToggled.emit($event);
    for (let i = 0; i <= this.displayColumns.length; i++) {
      if (columnId === this.displayColumns[i].columnName1) {
        this.displayColumns[i].toggled = !this.displayColumns[i].toggled;
      }
    }
  }

Here is an example array that I use to populate the table:


[{
    columnName1: 'Pickup',
    columnHeader1: 'Pickup',
    columnName2: 'Delivery',
    columnHeader2: 'Delivery',
    stackedHeader: true,
    stackedRow: true,
    toggled: false
  },
  {
    columnName1: 'FromCity',
    columnHeader1: 'From',
    columnName2: 'ToCity',
    columnHeader2: 'To',
    stackedHeader: true,
    stackedRow: true,
    toggled: false
  }]

Answer №1

The complete picture may be a bit blurry, with some parts missing, but I have some suggestions for refactoring the code to reduce errors.

Instead of passing the $event when defining click handlers in the template, you can pass any variable defined within the template itself.

<table mat-table [dataSource]="dataSource">
    <ng-container matColumnDef="{{column.columnName1}}" *ngFor = "let column of displayColumns">
        <!-- ... -->
            <!-- take note of the toggleColumn call below and the missing 'id' attribute -->
            <div ... (click) = "toggleColumn(column)" class = "column-header" >
        <!-- ... -->

This way, instead of receiving the DOM element, you receive the actual business object. This allows for the use of types and eliminates the need for an id on the clicked DOM element as well. The current implementation of toggleColumn seems a bit complex. Using a for-i loop can introduce errors, so it's better to use forEach which also enhances code readability due to fewer array references. Here's how I rewrote the method:

toggleColumn(selectedColumn: Column) {
    this.columnToggled.emit($event);
    this.displayColumns.forEach((otherColumn: Column) => {
        otherColumn.toggled = otherColumn.id === selectedColumn.id;
    });
  }

Upon further reflection, it appears that the issue might be that only the selected column's toggled field is being updated, while others remain unaffected. Check out the criteria within the if statement:

for (let i = 0; i <= this.displayColumns.length; i++) {
    if (columnId === this.displayColumns[i].columnName1) {
        this.displayColumns[i].toggled = !this.displayColumns[i].toggled;
    }
}

A simple solution could be to remove the if condition from the above statement and simply toggle the toggled state for all columns.

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

A step-by-step guide on implementing lazy loading for a specific div section using either AJAX or Java

I'm facing an issue with a div section that contains numerous tables pulled from my database. The main problem here is that when the page loads, it takes a considerable amount of time to fully load all the content, causing a significant delay. Could ...

What is the best way to prevent the body from scrolling when scrolling on a fixed div without making the body's scroll bar disappear?

Is there a way to prevent the body from scrolling while I scroll on a fixed div? I attempted using overflow:hidden for the body, which stops scrolling but causes the page to shake when the scroll bar disappears. Is there a solution that allows me to keep ...

Angular-Slickgrid experiencing issues with dropdown functionality

I recently downloaded the source code from this link and checked out the demo. However, I noticed that the single select dropdown functionality was missing in the demo. Therefore, I made some modifications to the code specifically for the last row "complet ...

Activate the click event repeatedly in a loop

I am currently working on a bookmarklet to extract information from my Indiegala bundles that I have purchased. Instead of gifting the entire bundle, I prefer sending individual games one or two at a time as it is more convenient with the individual gift U ...

Combining Multiple .ts Files into a Single File: A Simplified Application Structure with TypeScript 1.8

Currently, I am in the process of developing an Electron application and I have decided to implement TypeScript for this project. While TypeScript essentially boils down to JavaScript in the end, my familiarity with it makes the transition seamless. As of ...

What is the reason behind shadow dom concealing HTML elements when viewed in inspect mode?

https://i.stack.imgur.com/UZM7f.png Monday.com has implemented Shadow Dom to protect its source code. How can I work around this limitation? ...

Selenium fails to detect elements that are easily located by the browser using the aba elements, as well as through the use of JavaScript in the console

Looking to automate actions on the bet365 casino platform, but facing challenges with bot blocking mechanisms. Visit: Struggling to interact with elements within the "app-container" div using Selenium, however able to access them via JavaScript in the br ...

Having trouble getting my absolute div to center?

Check out this problem on my server at THIS LINK .login-div{ background: #fff none repeat scroll 0 0; height: 500px; left: 50%; width: 500px; right: 0; z-index: 99999; top: 20%; position: ...

Is there a better approach to verifying an error code in a `Response` body without relying on `clone()` in a Cloudflare proxy worker?

I am currently implementing a similar process in a Cloudflare worker const response = await fetch(...); const json = await response.clone().json<any>(); if (json.errorCode) { console.log(json.errorCode, json.message); return new Response('An ...

Converting Angular 5 select option values to strings is a must

I have set up a basic select connected to a variable like this: <select id="client" name="client" [(ngModel)]="order.clientId"> <option *ngFor="let client of clients" [value]="client.id"> {{ client.name }} </option> </ ...

Anticipate the middleware function to either invoke the next function or return a HTTP 400 status code

I am eager to delve into unit testing and am looking to test my Node API. I am utilizing Express with Typescript and Jest for testing. Prior to invoking the controller middleware, I apply the route input validation middleware to verify the validity of the ...

What is the best way to add attachments to the clipboard in a Chrome extension?

One possible way to achieve this is by using the navigator.clipboard.write API, but keep in mind that this API is not available to background pages of Chrome extensions. A method I attempted involved creating a blob like this: let blobFinal = null; // ...

Using Vue components in NativeScript-Vue popups: A comprehensive guide

To initiate the popup, I include the following code in a root component: import parentt from "./parentt.vue"; . . . this.$showModal(parentt, { fullscreen: true, }); The contents of parentt.vue are as follows: <template> <StackLayout> ...

The margin property in jQuery does not seem to be functioning properly when trying to send

Within the view page, there is jQuery code that sets a margin on a div. Below is the code: <script type='text/javascript'> $('#someID').css('margin-left', '10px'); </script> This code functions proper ...

The pageSize in React's Material Table does not reflect dynamic updates

Currently, I am attempting to implement pagination for material table data using TablePagination. One issue I am facing is that the pageSize property, initially defined as a state variable, does not update when the selected pageSizeOptions change. Despite ...

Adjusting MongoDB settings to permit cross-origin requests

I'm still new to using MongoDB, so I'm in the process of familiarizing myself with it. My current goal is to send a JSON object to MongoDB from the client side using the JavaScript code below. var addUserButton = document.getElementById('a ...

Using Angular 2 to bind ngModel to a property's reference

I have a lengthy list of inputs provided by users that I would like to store in an object instead of listing them out in HTML. My goal is to connect these values to another object that holds the data of the user or customer. I am looking to use ngModel for ...

Locating a Guild Member using their Alias

I need help locating a GuildMember using their nickname. The nickname is linked to their Roblox name upon joining the server, and I've configured a webhook to transmit a message in a specific channel containing their username and other related details ...

Error with Cross-Origin Resource Sharing (CORS) upon inserting a parameter within an Express application

I'm completely stumped as to why this isn't functioning properly. My express app is deployed on Heroku and here's the code: var urlMetadata = require('url-metadata') var express = require('express') var cors = require( ...

Ways to eliminate white space in bootstrap CSS menu bar

My goal is to create a responsive navigation bar using Bootstrap and customize it to fit my design needs. Although I was able to implement the dropdown on mobile-sized windows, I encountered a margin issue that I couldn't remove on the right side. I ...