Hi All,
I am using Ionic 2, and am trying to load a collection
of messages
in an <ion-scroll>
. My problem is, that the html
tries to render the message
items before they are ready I think. As a result, I get the following error:
As you can see, the message
item is undefined
.
Exception in queued task: EXCEPTION: Error in build/pages/messages/messages.html:65:9
ORIGINAL EXCEPTION: TypeError: Cannot read property 'ownership' of undefined
ORIGINAL STACKTRACE:
TypeError: Cannot read property 'ownership' of undefined
at DebugAppView._View_MessagesPage6.detectChangesInternal (MessagesPage.template.js:1062:70)
However, it does in fact render. I think this is due to the message
item being populated after.
html
<ion-content padding class="messages-page-content">
<ion-scroll scrollY="true" class="messages">
<div *ngFor="let message of messages" class="message-wrapper">
<div *ngIf="message.changeDate">
<center><span class="message-datetime">{{message.createdAt | amDateFormat: 'DD MMM YYYY'}}</span></center>
</div>
<div [class]="'message message-' + message.ownership">
<div class="message-content">local:{{message.content}}</div>
<span class="time-tick">
<span class="message-timestamp">{{message.createdAt | amDateFormat: 'h:mm a'}}</span>
<div *ngIf="message.readByReceiver && senderId == message.senderId">
<span class="checkmark">
<div class="checkmark_stem"></div>
<div class="checkmark_kick"></div>
</span>
</div>
</span>
</div>
</div>
</ion-scroll>
</ion-content>
ts
private messages: Mongo.Cursor<Message>;
this.messages = Messages.find({
chatId: this.activeChat._id
}, {
sort: { createdAt: 1 },
transform: this.transformMessage.bind(this)
});
Question
Is it possible to only let the html
start to load the collection when it is ready? Or, is the perhaps something else I am doing wrong? Why would it try iterate through the collection when its objects are still undefined
?
Thank you
maybe use an async pipe for this? so let message of messages | async
1 Like
Thanks luukschoen. That didnât work for me, it just cases nothing to render, does not iterate through the list.
I have changed the code to output âloading...
â if there message
item is undefined
. And it does display âloading...
â on the screen, implying that message
is undefined
. But I also log the output from !exists(message)
, and it indicates that message
is not undefined
. So it looks like the html
is not in agreement with the ts
.
html
<div *ngFor="let message of messages" class="message-wrapper">
<div *ngIf="!exists(message)">
<div *ngIf="message.changeDate">
<center><span class="message-datetime">{{message.createdAt | amDateFormat: 'DD MMM YYYY'}}</span></center>
</div>
<div [class]="'message message-' + message.ownership">
<div class="message-content">local:{{message.content}}</div>
<span class="time-tick">
<span class="message-timestamp">{{message.createdAt | amDateFormat: 'h:mm a'}}</span>
<div *ngIf="message.readByReceiver && senderId == message.senderId">
<span class="checkmark">
<div class="checkmark_stem"></div>
<div class="checkmark_kick"></div>
</span>
</div>
</span>
</div>
</div>
<div *ngIf="!message">
<p>loading...</p>
</div>
</div>
ts
public exists(message: Message): boolean {
console.log('exists: message = '+message.content+', exists = '+(this.localMessageIds.indexOf(message._id) > -1));
if (message) {
return this.localMessageIds.indexOf(message._id) > -1;
}
true;
}
output:
exists: message = test, exists = false
You can see that the message
item is not undefined
as it has a content
of âtest
â. But the screen displays:
loading...
I didnât read the topic properly yet⌠I missed the above error. That means ownership doesnt exist on the message, but it doesnât mean the message is undefined. Can you try to prefix ownership with a questionmark like this, so instead of using message.ownership doing this: message?.ownership
1 Like
Thanks, I will give that a try. But it still does not explain why loading...
is being outputted (thatâs when !message
)
What also would be an option is to just render the messages only if the length is greater then 0. In other words, donât do this: *ngIf="!exists(message)" but just check for the length of the array right away: *ngIf=âmessages.length > 0â . Now youâre sure everything inside is only called when the expression says the messages length is greater then zero.
1 Like
This just means what you probably already figured out yourself, that the variable messages is not really empty. Using the ! operator just queries for not message over here. I assume (assumption(!)) that message is not empty, but so thatâs why it says loading. If you want to know if message == null, you could use the double not operator !!message like that.
1 Like
Very strange. I am testing using:
<div *ngIf="message == null">
<p>loading...</p>
</div>
The console output shoes that message
is not null
.
exists: message = test3, exists = false
But I still get:
loading...
just check bij using *ngIf="!!message". Did you try the solution with the length operator?
1 Like
It doesnât display anything inside the:
<div *ngIf="messages.length > 0"> ... </div>
Previously it was before I put the check in place.
To me, this suggests it is a timing issue. The html
is trying to loop before the messages
are populated. It is iterating though, because I have this outside the if statement:
<div *ngIf="!!message">
<p>loading...{{messages.length}} and {{message}}</p>
</div>
and it outputs:
loading... and [object Object]
If you want to directly display the message, wrap it and pipe it (its probably json) do this:
{{ message | json }}
1 Like