Updating the color of specific buttons using ngFor in Typescript and Angular 8

I have successfully implemented a feature where text is displayed word by word using an ngFor directive. Within the ngFor loop, there is an if-else statement that determines whether each word should be displayed as a <span> or a <button>.

Now, I want to modify the behavior of the buttons so that when a user clicks on a button for the first time, its background color changes to red and on subsequent clicks, it reverts back to grey.

The issue I am facing is that currently, clicking on any button changes the background color of all buttons instead of just the one clicked on. How can I modify the code to change the color of only the clicked button?

HTML:

<div id="learnerText" *ngFor="let item of wordsJsonText; let i = index" [ngClass]="{active: i === activeIndex}">
  <div class="container" id="textBody" id="learnerText">
    <ng-container *ngIf="item.is_title==='false' && item.has_context==='false'; then caseA else caseB">
    </ng-container>
    <ng-template #caseA id="textBody" id="learnerText">
      <span id="learnerText">{{item.form}}</span>
    </ng-template>
    <ng-template #caseB>        
        <div *ngIf="item.is_title==='false' && item.has_context==='true'">
          <Button class="btn btn-secondary" [ngStyle]="{'background-color' : toggle ? 'red' : 'grey'}"
          id="bodyButton" text=item.form (click)="onClickMe(item.lemma, item.pos); toggleColor()">{{item.form}}</Button>
        </div>
    </ng-template>
  </div>
</div>

TYPESCRIPT

private toggle: boolean;

toggleColor() {
    this.toggle = !this.toggle;
}

Answer №1

In my personal experience, the most straightforward approach to achieve this task would be to introduce an additional field within each object in your wordsJsonText array - for instance, isToggled: boolean.

[{form: 'abc', isToggled: false}, {form: 'def', isToggled: false}]

Subsequently, you can implement the following logic on your button.

(click)="item.isToggled = !item.isToggled"

Utilize the value of item.isToggled to determine the class assigned to the button.

Answer №2

Here is a suggestion to enhance your code:

export interface JsonWordWrapper {
    jsonWord: JsonWord;
    checked: boolean;
}

toggleColor(item: JsonWrapper) {
    item.checked = !item.checked;
}

Instead of simply assigning wordsJsonText variable like this:

this.wordsJsonText = wordsJson

You can use the following approach:

this.wordsJsonText = wordsJson.map<JsonWrapper>(w => {
    jsonWord: w,
    checked: false
});

Update your HTML accordingly:

<button [ngStyle]="{'background-color' : item.checked ? 'red' : 'grey'}" (click)="toggleColor(item)" ...>{{ item.jsonWord.form }}</button>

This way, you can implement a more generic solution without altering your original json data structure.

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

Is searching for duplicate entries in an array using a specific key?

Below is an array structure: [ { "Date": "2020-07", "data": [ { "id": "35ebd073-600c-4be4-a750-41c4be5ed24a", "Date": "2020-07-03T00:00:00.000Z", ...

Best practices for updating the token in an Angular 2/5 application - tips on how, where, and when to refresh

Currently I am utilizing the following technologies: Django REST Framework Angular 5 RxJS + OAuth2 Within all components paths except LoginComponent, I have an AuthGuard to verify the token data stored in localstorage of the browser. If valid data is ...

What is the best way to increase a JSON value in a Typescript scenario? For instance, how can I add more

Is there a way to update JSON values in a TypeScript example by incrementing likes or dislikes when a button is clicked?https://i.sstatic.net/aon03.png movies: any[] = [ { name: "Fan", likes: 0, dislikes: 0, unseen: 0, fimage: "/images/fan.jpg" }, ...

Directly mapping packages to Typescript source code in the package.json files of a monorepo

How can I properly configure the package.json file in an npm monorepo to ensure that locally referenced packages resolve directly to their .ts files for IDE and build tooling compatibility (such as vscode, tsx, ts-node, vite, jest, tsc, etc.)? I want to a ...

Using subscribe method to return an observable within a function

Looking to develop a service that interacts with the Spotify API, I require an authorization bearer token. The token is obtained from another service, which returns an observable. How can these two components be integrated together? Initial attempt: getS ...

Assign a value to ReplaySubject if it is currently devoid of any

I am facing a challenge with my ReplaySubject in the component after content initialization. Whenever it initializes, it always gets set to "/api/bulletin/getall" value and overrides any value assigned to it before in the onViewChanged function. How can ...

Changing application security is threatened by sanitizing base64 images

I'm having some trouble displaying an image that I've converted to base64 encoding. data:image/vnd.microsoft.icon;base64,AAABAAIAICAAA..... No matter what I try, I always end up with the following error: { changingThisBreaksApplicationSecur ...

TypeScript and Node.js: The type of 'this' is implicitly set to 'any'

Help Needed with TypeScript issue: An issue is arising in my TypeScript code related to a mongoose schema's post function. It is used to generate a profile for a user upon signing up, using the User model. Even though the code functions properly, th ...

Tips for effectively navigating with the `Next-intl` and `next/link` componentsWhen working with the

I have implemented a next-intl library to enable multi-language support on my website. This means that the paths for different languages look like www.next.com/de or www.next.com/en Currently, I am utilizing NextJS 14. <NextLink href="/support-us& ...

How can we transfer a value from a parent component class to a child subclass?

In my TypeScript file, there are three classes within a single file. I am attempting to transfer a value from the MainComponent class to the TableContent class. I initially tried using super() inside the TableContent class which did not work, and then att ...

Tips for customizing md-autocomplete styling in Angular 4 using SCSS

I have developed an application that utilizes md-autocomplete from material.angular.io. The issue arises when I attempt to search for items, as the dropdown suggestions have a narrower width. Therefore, I am looking to expand the width of md-autocomplete. ...

Unable to utilize material tabs in this situation

Discovering the material tabs feature at https://material.angular.io/components/tabs/api#MatTab got me excited to implement it in my project. After adding the suggested import, I encountered an issue where I couldn't find the module "@angular/materia ...

Creating divs dynamically in a loop and displaying them upon clicking a button in Angular

I am trying to dynamically create divs in a loop and show the selected div when I press a specific button. In theory, this is how I envision it... <div>div1</div><button (click)="showDiv(divID)">showDIV</button> To hide a ...

Extending a type by adding properties from separate files using TypeScript

I am faced with a situation where I have a file containing either a type or interface variable (all of which are exported), and I need to add new properties to this variable from different files without using extends. Essentially, making changes to the sam ...

The absence of a semicolon in the non-null assertion is causing an

Within my code, I have a function that arranges a set of cards according to a specific coordinate system: const orderCardsInPage = (items: OrderItemType[], pageCards: CardType[]) => { return pageCards.sort((firstCard, secondCard) => { con ...

Angular neglects the specified animation timing

I created a sidebar component that relies on the sidebarExpanded state passed through Input(). Despite the correct animation trigger upon input change, the width adjustment happens abruptly. Interestingly, the same animation code works flawlessly in anothe ...

The browser is sending numerous requests for the audio tag

I am facing an issue with an audio tag in my code. The URL is being parsed and returned by a function. <audio class="fr-draggable" controls autoplay [src]="extractAudioUrl(message)" style="width:100%"></audio> Unfortunately, the browser ends ...

Reactive forms in Angular do not refresh or update automatically when a new error is added

Upon initializing my FormGroup in the ngOnInit() method, I invoke a validator function to ensure that the password and confirmPassword fields match. This is how it looks in TypeScript: regForm: FormGroup; constructor() { } ngOnInit() { this.regFo ...

What factors play a role in determining how modules are mapped to components in Angular 2?

What is the distribution method for modules on components? What benefits does this innovative concept offer compared to traditional folder organization? Choices: One module assigned to each component? One module designated per page. Other ... ...

Encountering ExpressionChangedAfterItHasBeenCheckedError in Angular 17 even after invoking detectChanges method

I'm encountering a minor problem with Angular and its change detection mechanism. I have created a simple form where additional input fields can be added dynamically. However, every time I click the add button, an ExpressionChangedAfterItHasBeenChecke ...