I’m rendering a message list and each message is render by a Message template.
From each template instance I need to access the data context of the previous message rendered – so the previous instance data context.
I need to do that within a helper.
I thought that something like this would work, but it doesn’t:
I’m not sure what you’re doing wrong. Have you considered creating a custom array and add the previous message to each array item, then use that for the list’s context ? like
It’s pretty strange. Debugging I observed that for some reason helpers are executed twice for each message record. How is that possible?
In effect what I observe is that if look into:
element = $(’#’ + Template.instance().data._id).get(0)
before = $(’#’ + Template.instance().data._id).prev().get(0);
I get:
Blaze.getData(element) === Blaze.getData(before)
Array solution: Yes, thanks, that is a possible way to solve the problem. Another one I thought is adding to each message data context, the previous message data context like here:
About Blaze.getView I suppose that I will get the same issue as Blaze.getData. I’m gonna try today.
It’s not really a good idea to try to access a sibling template’s data context like this. A better approach would be to make the parent list template ‘smart’ and then have the message templates take what they’re given and simply show it. This separation is discussed in the guide here.
E.g.: If you were calling your message template from within you list template like this: {{> myMessage (messageArgs message)}} then messageArgs would be a helper that might look a bit like:
Template.myList.helpers({
messageArgs(message) {
const instance = Template.instance();
return {
message,
active: instance.state.equals('activeMessage', message._id),
previousId: // From the parent is should be easy to access the previous id
makeMessageActive(messageId) { // A callback to have the child talk to the parent
instance.state.set('activeMessage', message._id);
}
};
}
});
The idea is that at the parent level you would have an array of all messages in context. So within that messageArgs helper if you have the id of the current message (message._id) then you only need to use underscore or jquery or whatever to find the previous item.
It’s possible that the whole array isn’t in context (with pagination for example) in which case you have to go to the server to get it so I guess for this you might need to have some sort of server side logic to take the current id and return the previous message to that one. Note. You want to do this inside the server method (or pub) because the client might not be aware of messages that have been deleted.
You mean I have to keep a copy of the messages in an array saved instance var (global to messages)?
In the end I did something similar using a global variable to the template and injecting part of the previous message context data to the current message context data:
<template name="messages">
{{#if Template.subscriptionsReady}}
{{#if noMessages}}
<div class="no-messages-yet">No messages posted yet. Be the first!</div>
{{else}}
{{#each msg in allMessages}}
{{> message (msgArgs(msg))}}
{{/each}}
{{/if}}
<spam id="bottom-page-anchor"></spam>
{{/if}}
</template>
It turns out that my approach creates a bunch of problems to the usual Blaze reactive behavior
I guess it depends of the fact that I injected new fields into current message context and that is a reactive space.
For example: when I delete a message from the list Blaze refreshes the entire list
I’d like add fields to the message data space without interfering with Blaze reactive rendering process.