Johnny Am
Johnny Am

Reputation: 75

*ngFor elements with different classes

I'm trying to have different classes to my buttons that are generated using the *ngFor. But once I toggle the class it would change the class for all previously created buttons, which I know is logical but I hope that there could be a way.

*more context: I have 2 search bars, both adding their text into the same array. the the content of the array is displayed in buttons. I want to differentiate between incoming data, so text from searchbar1 in blue and searchbar2 in orange, while keeping the order of selection, which is why I didn't separate them into 2 buttons.

newAction(text){
  this.classvalue = true;
  this.ConvMsgs.push("ChatBot: "+text);
    console.log(text);
  }
newIntent(text){
  this.classvalue =false;
this.ConvMsgs.push("User: "+text);
  console.log(text);
}
.msg_cotainer{
        margin-top: auto;
        margin-bottom: auto;
        margin-left: 10px;
        border-radius: 25px;
        background-color: #39adc7;
        padding: 10px;
    position: relative;
  }
  .msg_cotainer2{
        margin-top: auto;
        margin-bottom: auto;
        margin-left: 10px;
        border-radius: 0px;
        background-color: chocolate;
        padding: 10px;
    position: relative;
  }
<ng-container *ngFor="let button of ConvMsgs">
                  <br />
                  <button [ngClass]="classvalue? 'msg_cotainer':'msg_cotainer2'">{{button}}</button>
                  <br />
                </ng-container>

these functions are called upon clicking on results from the search bars.

Upvotes: 1

Views: 1534

Answers (3)

Rob Monhemius
Rob Monhemius

Reputation: 5144

At the moment you try to display a message by passing the message as a string. If you were to pass an object with a text and class property you would be able to set a custom class using that class property.

Below is an example, which you can also try in this StackBlitz.

app.component.html

<button *ngFor="let message of messages" [ngClass]='message.class'>{{message.text}}</button>

app.component.css

.action {
  background: red;
}
.intent {
  background: green;
}

app.component.ts

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  messages = [];

  ngOnInit() {
    this.newAction('Action 1');
    this.newAction('Action 2');
    this.newIntent('Intent 1');
  }

  newAction(text){
  this.messages.push({
    text: `Chatbot ${text}`,
    class: 'action'
  });
  }
  newIntent(text){
    this.messages.push({
    text: `User: ${text}`,
    class: 'intent'
  });
}
}

Upvotes: 1

Leandro Galluppi
Leandro Galluppi

Reputation: 915

If you only have a well-known number of buttons to render, you may try to use the index of the array to determinate which class is applied, something like this:

<ng-container *ngFor="let button of ConvMsgs; let i = index">
    <br />
    <button [ngClass]="'msg_cotainer' + i">{{ button.text }}</button>
    <br />
</ng-container>

Upvotes: 0

Obzi
Obzi

Reputation: 2390

You shoul'd use a boolean inside ConvMsgs :

newAction(text){
    this.ConvMsgs.push({
        text: "ChatBot: "+text,
        classvalue: true
    });
    console.log(text);
}
newIntent(text){
    this.ConvMsgs.push({
        text: "User: "+text,
        classvalue: false
    });
    console.log(text);
}
<ng-container *ngFor="let button of ConvMsgs">
    <br />
    <button [ngClass]="button.classvalue ? 'msg_cotainer' : 'msg_cotainer2'">{{ button.text }}</button>
    <br />
</ng-container>

Upvotes: 0

Related Questions