user10037542
user10037542

Reputation:

Change a List item's background in Typescript

I have a page, where in the top, there's a question, and below that, there's a list of answers, and you can add new answers too. (image below) enter image description here

In a format like (name of the user who answered) "válasza: ekkor: (date), which means his answer, at this time.
Below every question there are 3 buttons, + C and -, the ppl who asked the question can accept the answer (+), deny the answer (-) and cancel applying or denying (C).
Problem is, if I press any button for example in any row, the effect only applies to the first one.
Accept -> Green Background, Deny -> red, C -> white

Here's the HTML code:

<div class="container" style="...">
        <ul class="list-group">
            <li id="colorTarget" class="list-group-item" *ngFor="let comment of actualComments">

                <div style="...">
                    <b>{{comment.iro}}</b> válasza, ekkor: {{comment.mikor}} {{comment.leir}}
                </div><br/>

                <div class="row" style="width:120px;">
                    <div style="...">
                        <button class="btn btn-light" id="buttonTarget1" (click)="acceptAnswer(comment.iro,comment.mikor,comment.leir)">
                        +
                        </button>
                    </div>
                    <div style="...">
                        <button class="btn btn-light" id="buttonTarget2" (click)="clearAnswer(comment.iro,comment.mikor,comment.leir)">
                        C
                        </button>
                    </div>
                    <div style="...">
                        <button class="btn btn-light" id="buttonTarget3" (click)="denyAnswer(comment.iro,comment.mikor,comment.leir)">
                         -
                        </button>
                    </div>
                </div>

            </li>
        </ul>
    </div>

And the TypeScript:

acceptAnswer(iro, mikor, iras) {
    var x = this.answerid(iro, mikor, iras);         
    this.actualComments[x].accepted = 1;
    var target = document.getElementById("colorTarget");
    target.style.background = 'green';
    target.style.color = 'white';
  }

Deny and Clear Answer functions are exactly like this, but with red and white color.
If you have any idea..please.

So, in short: unique id to all li and pass this unique id to the functions.

Upvotes: 2

Views: 1625

Answers (2)

Andriy
Andriy

Reputation: 15462

try to use CSS classes on li elements:

<div class="container" style="...">
  <ul class="list-group">
    <li id="colorTarget" 
        class="list-group-item {{ statuses[i] }}" 
        *ngFor="let comment of actualComments; let i = index;">

      <div style="...">
        <b>{{comment.iro}}</b> válasza, ekkor: {{comment.mikor}} {{comment.leir}}
      </div>
      <br/>

      <div class="row" style="width:120px;">
        <div style="...">
          <button class="btn btn-light" 
                  id="buttonTarget1" 
                  (click)="statuses[i] = 'accept'; acceptAnswer(comment.iro,comment.mikor,comment.leir)">
            +
          </button>
        </div>
        <div style="...">
          <button class="btn btn-light" 
                  id="buttonTarget2" 
                  (click)="statuses[i] = 'clear'; clearAnswer(comment.iro,comment.mikor,comment.leir)">
            C
          </button>
        </div>
        <div style="...">
          <button class="btn btn-light" 
                  id="buttonTarget3" 
                  (click)="statuses[i] = 'deny'; denyAnswer(comment.iro,comment.mikor,comment.leir)">
            -
          </button>
        </div>
      </div>

    </li>
  </ul>
</div>

this way each li element will get CSS class ('accept', 'deny' or 'clear'). I made it inline within each button (click) function, it also could be dome in the TS file.

Now just add some SCSS:

li {
  &.accept {
    color: white;
    background: green;
  }
  &.deny,
  &.clear {
    color: white;
    background: red;
  }
}

or CSS:

li.accept {
  color: white;
  background: green;
}
li.deny,
li.clear {
  color: white;
  background: red;
}

If you need to isolate li's selection, you may add its ID to each li, like li#colorTarget

Now, in you TS file you do not need to deal with styling:

acceptAnswer(iro, mikor, iras) {
  var x = this.answerid(iro, mikor, iras);         
  this.actualComments[x].accepted = 1;
}

UPDATE

you wrote:

actualComment.accepted represent the accept/deny/clear colors

if I understand correctly, actualComment.accepted will have an integer representing one of three colors. If this is correct, let's assume 1 is green (accepted), 2 and 3 are red (deny and clear). In this case you could only change li from my original answer to:

<li id="colorTarget" 
        class="list-group-item" 
        [class.accept]="comment.accepted === 1"
        [class.deny]="comment.accepted === 2"
        [class.clear]="comment.accepted === 3" 
        *ngFor="let comment of actualComments">

or add public statusesMap (or ENUM) to your ts file:

statusesMap = {
  1: 'accept',
  2: 'deny',
  3: 'clear'
}

and in your HTML:

<li id="colorTarget" 
        class="list-group-item {{ statusesMap[comment.accepted] }}" 
        *ngFor="let comment of actualComments">

Upvotes: 1

R. Richards
R. Richards

Reputation: 25161

Here is what I came up with.

Updated template. Added a div, and moved the *ngFor to it to allow me to grab the data needed to create the id. The createId function build the id based on values used.

<div class="container">
<ul class="list-group">
    <div *ngFor="let comment of actualComments">
    <li [id]="createId(comment.iro,comment.mikor,comment.leir)" class="list-group-item">
        <div>
            <b>{{comment.iro}}</b> válasza, ekkor: {{comment.mikor}} {{comment.leir}}
        </div>
        <br/>
        …

    </li>
    </div>
</ul>
</div>

Addition to the component to create the id. This is used in the template above.

createId(iro, mikor, leir) {
    return `${iro}${mikor}${leir}`;
}

Update to acceptAnswer function to use the new id created using the new createId function.

acceptAnswer(iro, mikor, iras) {
    const x = this.answerid(iro, mikor, iras);
    this.actualComments[x].accepted = 1;
    const target = document.getElementById(this.createId(iro, mikor, iras));
    target.style.background = 'green';
    target.style.color = 'white';
}

Upvotes: 0

Related Questions