1

I'm new to Angular, working on my first app in Angular 8 and I want to toggle a component css class based on an objects array values.

The object is a post (test-data/posts.ts) with an array of likes

export const posts = [{
    id: 1,
    author: {},
    type: 'image',
    media: '',
    repost: 0,
    comments: [],
    likes: [ 1, 2, 3, 4]
}];

So my component typescript is this, to add and remove a like on the post, this is working

import { Component } from '@angular/core';

import { user } from '../test-data/user';
import { posts } from '../test-data/posts';

@Component({
    selector: 'app-feed',
    templateUrl: './feed.component.html',
    styleUrls: ['./feed.component.css'],
})
export class FeedComponent {
    posts = posts;
    user = user;

    liked = false;

    likePost(post) {
        // If post is liked, remove like
        if (this.isLiked(post)) {
            for (let i = 0; i < post.likes.length; i++) {
                if (post.likes[i] === user.id) { post.likes.splice(i, 1); }
            }
        // If not liked add a new like
        } else {
            post.likes.push(user.id);
        }
        // DEBUG: Log post data
        console.log(post);
    }

    isLiked(post) {
        return post.likes.includes(user.id);
    }
}

I can retrieve the object, add/remove likes with the component, but how do I check the array to determine is the post should display as liked or unliked?

My current html template is this, I'd like the to have an extra class "feed-icon-red" if the user id (user.id) appears in the posts like array (post.likes)

<div *ngIf="posts.length">
    <div *ngFor="let post of posts">
        <mat-list>
            <!-- Post Media -->
            <img class="feed-image" [src]="post.media" (dblclick)="likePost(post)"/>

            <!-- Interaction Button Row -->
            <mat-list-item>
                <span>
                    <mat-icon mat-list-icon class="ti-heart" [class.feed-icon-red]="" (dblclick)="likePost(post)"></mat-icon>
                </span>
            </mat-list-item>
        </mat-list>
    </div>
</div>

EDIT: I'd like to check for a specific value within the array to set the class. e.g. if (post.likes.includes(1)) set the icon class to 'feed-icon-red'

10
  • So do you want to display like count? Commented Jul 14, 2019 at 6:50
  • @PrashantPimpale no I don't want to display count, I just want to add a class to change the color to red Commented Jul 14, 2019 at 6:52
  • use ngClass as demonstrated here Commented Jul 14, 2019 at 6:53
  • @Musa Okay then check ngClass. Try and let us know working or not Commented Jul 14, 2019 at 6:57
  • 1
    Thanks @PrashantPimpale I implemented [class.feed-icon-red]="isLiked(post)" within my html and it works Commented Jul 14, 2019 at 7:11

2 Answers 2

1

You can use ngClass:

[ngClass]="isLiked(post) ? 'feed-icon-red' : ''"

Or even this is also working:

[class.feed-icon-red]="isLiked(post)"

HTML Code:

<div *ngIf="posts.length">
    <div *ngFor="let post of posts">
        <mat-list>
            <!-- Post Media -->
            <img  width=300 class="feed-image" [src]="post.media" (dblclick)="likePost(post)"/>
            <!-- Interaction Button Row -->
            <mat-list-item>
              {{isLiked(post)}}
                <span [ngClass]="isLiked(post)? 'feed-icon-red': ''"> Test
                    <mat-icon mat-list-icon class="ti-heart"  (dblclick)="likePost(post)"></mat-icon>
                </span>
            </mat-list-item>
        </mat-list>
    </div>
</div>

Working-Demo

Sign up to request clarification or add additional context in comments.

Comments

0

There seems to be an issue with your logic to determine whether a post has been liked or not.

Here, give this a try:

import { Component } from '@angular/core';
import { user } from './test-data/user';
import { posts } from './test-data/posts';

/**
 * @title Basic list
 */
@Component({
  selector: 'list-overview-example',
  templateUrl: 'list-overview-example.html',
  styleUrls: ['list-overview-example.css'],
})
export class ListOverviewExample {
  posts = posts;
  user = user;

  liked = false;

  likePost(post) {
    // If post is liked, remove like
    if (this.isLiked(post)) {
      post.likes.splice(post.likes.indexOf(this.user.id), 1);
      // If not liked add a new like
    } else {
      post.likes.push(this.user.id);
    }
    // DEBUG: Log post data
    console.log(post);
  }

  isLiked(post) {
    return post.likes.includes(this.user.id);
  }
}

And in your template:

<div *ngIf="posts.length">
    <ul>
    <li *ngFor="let post of posts">
        <!-- Post Media -->
        <img class="feed-image" [src]="post.media" (dblclick)="likePost(post)"/>
    <!-- Interaction Button Row -->
    <span [class.feed-icon-red]="post.likes.includes(user.id)" (dblclick)="likePost(post)">❤</span>
    </li>
  </ul>
</div>

Here's a Working Sample StackBlitz for your ref.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.