0

The first screenshot is a console log of the array(messageSplit) I want to display. The second screenshot is how I want the data to look when it's displayed - basically each item of the sub arrays in a td table element.

I have tried the below code, but this gives the dreaded 'Expression has changed after it was checked' error.

<div *ngFor="let item of messageSplit[increment()];
     <td>{{item}}</td>
</div>

increment() {
    if (this.counter < this.messages.length) {
    return this.counter++;
}

Please can someone explain the right way to go about doing this?

The below code will output as shown in screenshot 3 and is not the desired output as all of the sub arrays are inside a single td element

<div *ngFor="let message of messageSplit;">
    <td *ngFor="let item of message">{{item}}</td>
</div>

Below is the full code for the particular tr

<tr *ngFor="let message of messages" [routerLink]="['/members', 
     messageContainer == 'Outbox' ? message.recipientId : 
     message.senderId]" [queryParams]="{tab:'3'}">
     <div *ngFor="let message of messageSplit"> 
         <td *ngFor="let item of message"> {{item}}></td>
     </div>    

     <td>
         <div *ngIf="messageContainer != 'Outbox'">
            <!-- <img [src]="message.senderPhotoUrl" class="img-circle"> -->
            <strong *ngIf="message.senderId == 1">Boost Promotions</strong>
            <strong *ngIf="message.senderId == 2">Lion</strong>
         </div>
         <div *ngIf="messageContainer == 'Outbox'">
            <strong *ngIf="message.recipientId == 2">Boost 
                Promotions</strong>
            <strong *ngIf="message.recipientId == 1">Lion</strong>
         </div>
         </td>
         <td>
           <small class="text-muted">
            <span class="fa fa-clock-o">{{message.messageSent | timeAgo}} 
            </span>
            <span *ngIf="!message.isRead" class="text-muted text-danger"> 
            (Unread)</span>
            <span *ngIf="message.isRead" class="text-muted text-success"> 
            (Seen)</span>
           </small>
        </td>
     <td>
</tr> 

messageSplit

enter image description here

enter image description here

enter image description here

4
  • Why not just use an *ngFor inside another *ngFor? Like so: <div *ngFor="let message of messageSplit"> <td *ngFor="let item of message">{{item}}</td> </div> Commented Apr 8, 2018 at 22:07
  • @AmitB. If I do it that way, it displays every sub array in a single td, and repeats for the amount of messages Commented Apr 8, 2018 at 22:12
  • The best approach for your case is having the loop on code-behind and populating proper values there and then send object to client side and just show that values. Not sure but probably you need some changes on your object. Commented Apr 8, 2018 at 23:35
  • @Hadee thanks, I think I will take this approach if I can't find a solution soon on the client side Commented Apr 9, 2018 at 0:05

3 Answers 3

3

I think your problem can be solved if you correctly use <tr>. I have tried your code with data similar to yours, and to make it works as you expect (your second screenshot), I have written the code like this:

  <tr *ngFor="let message of messages; let i = index">
    <td>
      <div *ngFor="let item of messageSplit[i]">{{item}}</div>
    </td>

    <td>
     // your next td (From)
    </td>

    <td>
     // your next td (Received)
    </td>
</tr>

This is the code that I have tested: plunker

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

10 Comments

I already have a template binding on my tr element but I this makes sense and so I will see if I can refactor
You can use the row number and make the td like this: <td><div *ngFor="let item of messageSplit[index]">{{item}}</div></td>. where index is a variable that you set to indicate the row number.
From what I understand, you can't use 'index' in that way as I've already tried: <div *ngFor="let item of messageSplit[index]; let i = index"><td>{{item}}</td></div>
no I didn't mean by index to be like that. what I meant is if you don't want to change your tr then try to keep a counter that indicates your row number and use it. So if you name your counter count use it like this: <td><div *ngFor="let item of messageSplit[count]">{{item}}</div></td>. I used index as a name instead of count so this was a little confusing, sorry :)
Sorry my bad, but what is incrementing the counter? I tried something like this as you can see from the code in my question, and it temporarily works, but calling a method from the html causes errors
|
0

You could try to iterate it using two *ngFor loops:

<div *ngFor="let message of messageSplit;">
    <td *ngFor="let item of message">{{item}}</td>
</div>

The first loop will take each array inside of your multidimensional array, and the second one will take each individual element of that inner array.

8 Comments

Just tried doing this, but it displays every sub array in a single td element and repeats for the amount of messages
So "item" is an array itself? Could you console.log it?
Same issue, the only difference is, with this way each element in the sub arrays are displayed inline whereas before they were on a new line
The first screenshot is a console log of the messages array
Maybe you want to add a <tr> for each element? Try change the <div> for a <tr> and see what happens
|
0

Try this:

                <td>{{ message.from }}</td>
                <td>{{ message.Received}}</td>  </tr>

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.