I am building a chat application and on my "new chats" page I have a list of contacts, which you can select one by one by tapping them (upon which I apply a CSS selected class and push the user id into an array called 'newChatters'.
I want to make this array available to a helper method so I can display a reactive list of names, with all users who have been added to the chat.
The template that I want to display the reactive list in:
<template name="newChatDetails">
<div class="contactHeader">
<h2 class="newChatHeader">{{newChatters}}</h2>
</div>
</template>
The click contactItem event triggered whenever a contact is selected:
Template.contactsLayout.events({
'click #contactItem': function (e) {
e.preventDefault();
$(e.target).toggleClass('selected');
newChatters.push(this.username);
...
The newChatters array is getting updated correctly so up to this point all is working fine. Now I need to make {{newChatters}} update reactively. Here's what I've tried but it's not right and isn't working:
Template.newChatDetails.helpers({
newChatters: function() {
return newChatters;
}
});
How and where do I use Deps.autorun() to make this work? Do I even need it, as I thought that helper methods auto update on invalidation anyway?
1) Define Tracker.Dependency
in the same place where you define your object:
var newChatters = [];
var newChattersDep = new Tracker.Dependency();
2) Use depend()
before you read from the object:
Template.newChatDetails.newChatters = function() {
newChattersDep.depend();
return newChatters;
};
3) Use changed()
after you write:
Template.contactsLayout.events({
'click #contactItem': function(e, t) {
...
newChatters.push(...);
newChattersDep.changed();
},
});
You should use the Session
object for this.
Template.contactsLayout.events({
'click #contactItem': function (e) {
//...
newChatters.push(this.username);
Session.set('newChatters', newChatters);
}
});
and then
Template.newChatDetails.helpers({
newChatters: function() {
return Session.get('newChatters');
}
});
You could use a local Meteor.Collection
cursor as a reactive data source:
var NewChatters = new Meteor.Collection("null");
Template:
<template name="newChatDetails">
<ul>
{{#each newChatters}}
<li>{{username}}</li>
{{/each}}
</ul>
</template>
Event:
Template.contactsLayout.events({
'click #contactItem': function (e) {
NewChatters.insert({username: this.username});
}
});
Helper:
Template.newChatDetails.helpers({
newChatters: function() { return NewChatters.find(); }
});
To mimick the behaviour of Session
without polluting the Session
, use a ReactiveVar
:
Template.contactsLayout.created = function() {
this.data.newChatters = new ReactiveVar([]);
}
Template.contactsLayout.events({
'click #contactItem': function (event, template) {
...
template.data.newChatters.set(
template.data.newChatters.get().push(this.username)
);
...
Then, in the inner template, use the parent reactive data source:
Template.newChatDetails.helpers({
newChatters: function() {
return Template.parentData(1).newChatters.get();
}
});
for people who is looking for a workaround for this in the year 2015+ (since the post is of 2014).
I'm implementing a posts wizard pw_module
where I need to update data reactively depending on the route parameters :
Router.route('/new-post/:pw_module', function(){
var pwModule = this.params.pw_module;
this.render('post_new', {
data: function(){
switch (true) {
case (pwModule == 'basic-info'):
return {
title: 'Basic info'
};
break;
case (pwModule == 'itinerary'):
return {
title: 'Itinerary'
};
break;
default:
}
}
});
}, {
name: 'post.new'
});
Later in the template just do a:
<h1>{{title}}</h1>
The navigation that updates the URL looks like this:
<nav>
<a href="{{pathFor route='post.new' pw_module='basic-info'}}">Basic info</a>
<a href="{{pathFor route='post.new' pw_module='itinerary'}}">Itinerary</a>
</nav>
Hope it still helps someone.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.