Updating icon of a row in a table based on its position with *ngFor

I am currently working with a table that contains a list of songs. My goal is to toggle the source of an icon in a specific row based on its index (for actions like play/pause, like/unlike). However, at the moment, the icon only changes in the first row regardless of the selected row.

You can find the working stackblitz example here: https://stackblitz.com/edit/github-zhvgft?file=src/app/play-list-page/play-list-page.component.html

Component.html

<table *ngIf="playListSongs.tracks.length > 0">
<thead>
<tr>
<th></th>
<th></th>
<th>title</th>
<th>artist</th>
<th>album</th>
<th>release date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let song of playListSongs?.tracks | search:searchTerm; let i = index;" [class.selected]="i==selectedRow">
<td>
<img src="../assets/play_line_icon.png" class="playBtn" (click)="togglePlaystateSong(song.track_id);getSongInfo(song);setClickedRow(i)" id="imgClickAndChange">
</td>
<td><img src="..\assets\not_liked.png" id="likedImg" (click)="toggleLikedSongs(song.track_id);setClickedRow(i)" style="cursor:pointer"></td>
<td> {{song.name}}</td>
<td>{{song.artists_names}}</td>
<td>{{song.album_name}}</td>
<td>{{song.release_date | date: 'yyyy-MM-dd'}}</td>
</tr>
</tbody>
</table>

Component.ts

//Row's index
setClickedRow(index: any) {
this.selectedRow = index;
console.log("this.selectedRow index:", this.selectedRow);
}

//Toggle liked/unlike 
toggleLikedSongs(id:any){
let likedImg = <HTMLInputElement>document.getElementById("likedImg");
this.playListsAPI.getLikeSongs().subscribe(data=>{
this.likedSongsArray = data
})
for(let i=0;i<this.likedSongsArray.liked_tracks.length;i++){
if(this.likedSongsArray.liked_tracks[i].track_id == id){
this.playListsAPI.MarklikedSongs(id,false).subscribe((data:any)=>{
this.likedSong = data
console.log("removed:", id);
likedImg.src = "../assets/not_liked.png"
})
break;
} else {
this.playListsAPI.MarklikedSongs(id,true).subscribe((data:any)=>{
this.likedSong = data
console.log(" added:",  id, this.selectedRow);
likedImg.src = "../assets/liked.png"
})
break;
}
}
}

//Toggle play/pause
togglePlaystateSong(id: number) {
let image = <HTMLInputElement>document.getElementById("imgClickAndChange");
let image2 = <HTMLInputElement>(
document.getElementById("imgClickAndChange2"));
if (!this.selectedSong || this.selectedSong.track_id !== id) {
const token = this.playListsAPI.generateToken();
const songUrl = `http://api.sprintt.co/spotify/play/${id}?access=${token}`;
this.player.src = songUrl;
this.player.load();
this.player.play();
image.src = "../assets/pause_line_icon.png";
image2.src = "../assets/controller_icons/bar_pause.png";
} else {
if (this.player.paused) {
this.player.play();
image.src = "../assets/pause_line_icon.png";
image2.src = "../assets/controller_icons/bar_pause.png";
} else {
this.player.pause();
image.src = "../assets/play_line_icon.png";
image2.src = "../assets/controller_icons/bar_play.png";
}
}
}

Your help is greatly appreciated!

Answer №1

Each image should have a unique ID, not all using imgClickAndChange.

<img src="../assets/play_line_icon.png" class="playBtn" 
    (click)="togglePlaystateSong(song.track_id);
    getSongInfo(song);
    setClickedRow(i)" 
    id="imgClickAndChange">

Ensure uniqueness by using song.track_id. .

<img src="../assets/play_line_icon.png" class="playBtn" 
    (click)="togglePlaystateSong(song.track_id);
    getSongInfo(song);
    setClickedRow(i)" 
    id="imgClickAndChange + {{song.track_id}}">


 togglePlaystateSong(id: number) {

     let image = <HTMLInputElement>document.getElementById("imgClickAndChange" + id);

     // rest of the code
  }

Remember to make IDs unique for proper addressing in all methods.

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

Automatically forwarding to another page in Angular 4 due to idle time

Is it possible to implement a timeout feature for inactivity on a webpage? For example, if a user is idle for 20 seconds without interacting with the page, can we automatically redirect them to the home screen? I've been struggling to get this functi ...

What is the method for referencing a subtype within an established type?

When working with React-native, I came across a component called FlatList which includes a property known as ListHeaderComponent. My question is how to specify the type of this property without having to manually copy and paste the original type. Currentl ...

Announce enhancements to a Typescript library

Utilizing Sequency's extendSequence() feature to enhance all Sequence instances with a custom method: import Sequence, { extendSequence, isSequence } from 'sequency' import equal from '@wry/equality' class SequencyExtensions { e ...

Problem with the Auto-fill Feature in PrimeNG Module

Check out my code on Gist:   https://gist.github.com/rickymuvel/8ddc4d14d90877329447ddde9c0aa835 The issue I'm facing involves the Autocomplete module in PrimeNG. It seems that the specific path in the ubigeo.service.ts file is not being called. Her ...

An issue has been identified with React's HTML input maxLength feature where it does not display an error

Within my form, I have an input field that currently does not include validation for a maximum length. <input type="text" className="form-control" id="company" onBlur= ...

Can you effectively leverage a prop interface in React Typescript by combining it with another prop?

Essentially, I am looking to create a dynamic connection between the line injectComponentProps: object and the prop interface of the injectComponent. For example, it is currently set as injectComponentProps: InjectedComponentProps, but I want this associat ...

React Component not displaying properly when used inside a map iteration

I am currently working on rendering multiple components using the .map method on an array with specific content. Although I can't find any errors in the console, the component is not appearing in the DOM as expected. I attempted to set subHeader to nu ...

Looping Feature in Ionic Framework's Slides Component

Currently, I am working on developing an application using Ionic-Angular. When it comes to incorporating slides in my app, I opted for the ionic 4 ion-slides component. Everything was going smoothly until I wanted to enable looping for the slides so that u ...

What limitations prevent me from using "await .getAttribute()" in Protractor, despite the fact that it does return a promise?

I have been working on transitioning my Protractor tests from using the selenium control flow to async/await. However, I am facing an issue where it is not allowing me to use await for the .getAttribute() function. Each time I try, I receive the error mess ...

What are the steps to conduct a vulnerability scan on an Angular/Node application?

I'm in the process of setting up a vulnerability check for my Angular 7/Node project. Can anyone advise on how to effectively run this type of process? Are there any recommended tools available? Initially, I attempted to use the dependency-check-mave ...

Deploying Initial Node+Express+Angular Application in Production

Embarking on my first endeavor to develop a Node.js Express app with Angular 7 for deployment in production has me pondering the following: What is the recommended folder structure for this project? Should I maintain separate projects for Node and An ...

Creating a function in Angular to locate each object based on its ID

Hello there, I am currently working on creating a method called findChildByIdInData(data:any, childId:string). This method will take in a JSON main node with children that have unique IDs, and the goal is to find a specific object based on the ID provided ...

Ensure that dynamic functions are accurately typed within a proxy utilizing TypeScript

I am currently working on a unique function that utilizes a Proxy with a get trap to extract functions from multiple objects. The challenge I am facing is getting TypeScript to recognize these functions at compile time so that I can add them to my interfac ...

How can we pass an optional boolean prop in Vue 3?

Currently, I am in the process of developing an application using Vue 3 and TypeScript 4.4, bundled with Vite 2. Within my project, there exists a file named LoginPage.vue containing the following code: <script lang="ts" setup> const props ...

What is the best way to activate an <ion-datetime> with an <ion-button>?

Im currently attempting to execute the following action: I would like to select only the month and year using the example below: <ion-datetime presentation="month-year"></ion-datetime> However, I do not wish for this label to be vis ...

Enhancing Angular HighChartsIs it time to rev

There seems to be an issue with the highchart not redrawing itself when dynamically changing plot options. I have integrated Highcharts into my code as shown below: In the HTML: <highcharts-chart [Highcharts]="Highcharts" [options]="opt ...

Issue: The function (0, react__WEBPACK_IMPORTED_MODULE_1__.useActionState) is not recognized as a valid function or its output is not iterable

I found a great example of using useActionState at this source. Currently, I am implementing it in my project with Next.js and TypeScript. app/page.tsx: "use client"; import { useActionState } from "react"; import { createUser } from ...

Is it possible to dynamically adjust the container size based on its content with the help of *ngIf and additional directives?

I have a single-image container that I need to resize when editing the content. The size should adjust based on the incoming content. See the images of the containers below: Image 1: This is the container before clicking on the edit button. https://i.sst ...

Error encountered during npm installation - EPERM: Operation not allowed

Today's challenge began when attempting to run the angular4 project and encountering this error: npm install eperm operation not permitted. In an effort to resolve it, I decided to delete the node modules folder and try again. However, upon running np ...

The directive is dynamically altering the disable attribute of its parent element

I am faced with a scenario where I have both a button and a directive in my template. The button can be disabled based on certain parameters defined in the template itself, as well as by the directive (it gets disabled in case of a double click event). B ...