Update function returns an error - meteor

This code returns an "Error: $scope.todoItems.update is not a function"
(in markDone function)
As I can see in console, $scope.todoItems has functions like save(), remove() but not an update() function, but as I can see here I writing it right.
Is something that I doing is wrong? More information would be helpful?
TodoItems = new Mongo.Collection('todoItems');
if(Meteor.isClient){
angular.module('todo_am', ['angular-meteor']);
angular.module('todo_am').controller('OutputListCtrl', ['$scope', '$meteor',
function($scope, $meteor){
$scope.todoItems = $meteor.collection(TodoItems);
$scope.remove = function(todoItem){
$scope.todoItems.remove(todoItem);
};
$scope.saveCustom = function(todoItem){
todoItem.isRead = false;
$scope.todoItems.save(todoItem);
};
$scope.markDone = function(todoItem){
console.log('>>> 4', todoItem);
console.log('>>> 5', $scope.todoItems);
$scope.todoItems.update(todoItem._id, { $set: { isRead: true }}); // <<<<<<<<< This line returns error
};
$scope.markUndone = function(todoItem){
todoItem.isRead = true;
$scope.todoItems.update(todoItem);
};
}]);
}
------------------------------ UPDATE --------------------------------
This is working:
if(Meteor.isClient){
angular.module('todo_am', ['angular-meteor']);
angular.module('todo_am').controller('OutputListCtrl', ['$scope', '$meteor',
function($scope, $meteor){
$scope.todoItems = $meteor.collection(TodoItems);
$scope.remove = function(todoItem){
$scope.todoItems.remove(todoItem);
};
$scope.saveCustom = function(todoItem){
todoItem.isRead = false;
$scope.todoItems.save(todoItem);
};
$scope.markDone = function(todoItem){
TodoItems.update({ _id: todoItem._id }, { $set: { isRead: true }});
};
$scope.markUndone = function(todoItem){
TodoItems.update({ _id: todoItem._id }, { $set: { isRead: false }});
};
}]);
}
------------------------------ UPDATE2 --------------------------------
This is whole code. I do not know if it's a right solution or not but it works.
Is there any example for update exists record in DB?
$ meteor --version
Meteor 1.1.0.2
As I can see in .meteor/versions file:
angular:angular#1.3.15_1
urigo:angular#0.8.6
index.html
<body ng-app="todo_am">
<div ng-controller="OutputListCtrl">
<div ng-include="'output-list.ng.html'"></div>
<div ng-include="'insert-new-form.ng.html'"></div>
</div>
</body>
index.ng.html
<p>Nothing</p>
insert-new-form.ng.html
<div>
<input type="text" ng-model="newTodoItem.text" />
<button ng-click="saveCustom(newTodoItem); newTodoItem='';" >Add New</button>
</div>
output-list.ng.html
<div>
<ul>
<li ng-repeat="todoItem in todoItems">
<p>
{{ todoItem.text }}
<span ng-switch on="todoItem.isRead">
<span ng-switch-when="true">
<button ng-click="markUndone(todoItem)">Mark Undone</button>
</span>
<span ng-switch-default>
<button ng-click="markDone(todoItem)">Mark Done</button>
</span>
</span>
<button ng-click="remove(todoItem)">X</button>
</p>
</li>
</ul>
</div>
app.js
TodoItems = new Mongo.Collection('todoItems');
if(Meteor.isClient){
angular.module('todo_am', ['angular-meteor']);
angular.module('todo_am').controller('OutputListCtrl', ['$scope', '$meteor',
function($scope, $meteor){
$scope.todoItems = $meteor.collection(TodoItems);
$scope.remove = function(todoItem){
$scope.todoItems.remove(todoItem);
};
$scope.saveCustom = function(todoItem){
todoItem.isRead = false;
$scope.todoItems.save(todoItem);
};
$scope.markDone = function(todoItem){
TodoItems.update({ _id: todoItem._id }, { $set: { isRead: true }});
};
$scope.markUndone = function(todoItem){
TodoItems.update({ _id: todoItem._id }, { $set: { isRead: false }});
};
}]);
}
if(Meteor.isServer){
Meteor.startup(function(){
/**
* If DB is empty, add some todoItems just for DEV purposes
*/
if (TodoItems.find().count() === 0) {
var todoItems = [
{
'text': 'First todo first todo first todo first todo first todo first todo first todo first todo first todo',
'isRead': true,
'userPosted': 'Vasia'
},
{
'text': 'Second todo item',
'isRead': false,
'userPosted': 'Fedia'
},
{
'text': 'Third todo item',
'isRead': true,
'userPosted': 'Vasia'
}
];
for (var i = 0; i < todoItems.length; i++)
TodoItems.insert({text: todoItems[i].text, isRead: todoItems[i].isRead});
}
});
}

That doesn't look like $scope.todoItems is a Meteor collection. If you look through the documentation you linked (http://docs.meteor.com/#/full/mongo_collection) - there's no reference to Meteor's Mongo Collections having a "save" method.
It looks like you're using an "Angular Meteor Collection" - http://angularjs.meteor.com/api/AngularMeteorCollection
In which case a simple call to ".save" should do it. Perhaps something like this:
$scope.markDone = function(todoItem){
todoItem.isRead = true;
$scope.todoItems.save(todoItem);
};

Related

Vue-Full-Calendar refetch-events error

I am having issues refreshing events when I add a new one. The event gets inserted into the database fine, but the call to
this.$refs.calendar.$emit('refetch-events')
Throws the following error:
[Vue warn]: Error in event handler for "refetch-events": "TypeError: $(...).fullCalendar is not a function"
Here is some more of the code to further demonstrate what I am trying to do:
<template>
<div>
<full-calendar ref="calendar" :event-sources="eventSources" #day-click="daySelected" #event-selected="eventSelected" :config="config"></full-calendar>
<!-- Modal Component -->
<b-modal ref="my_modal" title="New Appointment" #ok="submit" #shown="clearModalValues">
<form #submit.stop.prevent="submit">
<label>Client:</label>
<b-form-select v-model="selectedClient" :options="clientOptions" class='mb-3'></b-form-select>
<label>Service:</label>
<b-form-select multiple v-model="selectedService" :options="serviceOptions" class='mb-3'></b-form-select>
<label>Start time:</label>
<time-picker v-model="myTime"></time-picker>
<label>Notes:</label>
<b-form-input textarea v-model="notes" placeholder="Notes"></b-form-input>
</form>
</b-modal>
<!-- /Modal Component -->
</div>
</template>
<script>
export default {
props: {
staff:{
type: Number,
required: true
},
},
data() {
return {
myTime: new Date(),
selectedService: [null],
selectedClient: null,
selectedStartTime: new Date(),
notes: null,
serviceOptions: [],
clientOptions: [],
events: [],
config: {
timeFormat: 'h(:mm)',
eventClick: (event) => {
console.log('Event Clicked: '+event.title);
},
},
selected: {},
};
},
computed: {
eventSources() {
return [
{
events(start, end, timezone, callback) {
axios.get('/getEvents').then(response => {
callback(response.data)
})
}
}
]
}
},
mounted() {
this.myTime = new Date()
axios.get('/getClients').then(response => this.clientOptions = response.data);
axios.get('/getServices').then(response => this.serviceOptions = response.data);
},
methods: {
clearModalValues() {
this.selectedService = [null];
this.selectedClient = null;
this.selectedStartTime = new Date();
this.myTime = new Date();
this.notes = null;
},
submit(e) {
axios.post('/addEvent/',{'selectedService':this.selectedService,'selectedClient':this.selectedClient,'selectedStartTime':this.selectedStartTime,'notes':this.notes}).then(function(response){
//console.log(response.data);
new PNotify({
title: 'Success',
text: 'New event has been created',
icon: 'icon-checkmark3',
type: 'success'
});
this.selectedService = [null];
this.selectedClient = null;
this.selectedStartTime = new Date();
this.notes = null;
this.myTime = new Date();
// ******** I HAVE TRIED THESE CALLS AS PER DOCUMENTATION **********
//this.$refs.calendar.fireMethod('refetch-events')
//this.$refs.calendar.fullCalendar.$emit('refetch-events');
//this.$refs.calendar.$emit('refetch-events');
console.log(this.$refs.calendar);
}.bind(this));
},
eventSelected(event) {
console.log('Event Selected: '+event.title);
},
daySelected(date,event,view){
this.$refs.my_modal.show();
this.selectedStartTime = date.format("YYYY-MM-DD HH:mm:ss");
this.myTime = date.toDate();
},
},
};
</script>
According to the documentation it should be correct. I know its late and I have been at this for a couple hours so I might be overlooking something simple. Again this is vue-full-calendar and not regular full-calendar. I just need to call refetchEvents when I add the new events in the submit method. Thanks!
I have found the issue, thanks to Brock for the help. I had multiple versions of jquery running(the html template I was using was also calling it).

How to get all checkbox props with React + ASP.net mvc

I am learning React and ASP.net( not core).
I try to create a small project for practice.
I have a number of checkboxes and a submit button.
The idea is when I click on the button I want to create a Jason that will contain a list of the checkboxes text and their states (check \uncheck).
That Jason I want to send to the server.
I mange to create the components and the relevant events.
But fail to create the following
1) Get the state of the checkbox from the submit component and create a Jason out of it.
2) Send that Jason to the server side (ASP.net).
I try to flow the tutorial but didn’t get it, I tried to find solution on the internet but with no lack.
If someone can show me how to do it – or give me some direction that will help
Thanks
the jsk:
var data = [
{ Id: 1, ActionItem: "Action1" },
{ Id: 2, ActionItem: "Action2" },
{ Id: 3, ActionItem: "Action3" }
];
var Checkbox = React.createClass({
getInitialState: function() {
return {
isChecked: false
};
},
toggleChange: function() {
this.setState({
isChecked: !this.state.isChecked
},
function() {
console.log(this.state);
}.bind(this));
},
render: function() {
return (
<label>
<input type="checkbox"
checked={this.state.isChecked}
onChange={this.toggleChange} />{this.props.chkboxlabel}<br />
</label>
);
}
});
var ActionBox = React.createClass({
render: function() {
return (
<div className="actionBox">
<h1>Select Action </h1>
<CheckboxList data={this.props.data} />
<SubmitForm/>
</div>
);
}
});
var CheckboxList = React.createClass({
render: function() {
var actionNodes = this.props.data.map(function(action) {
return (
<Checkbox chkboxlabel={action.ActionItem} key={action.id}>
{action.ActionItem}
</Checkbox>
);
});
return (
<form className="actionList">{actionNodes}
</form>
);
}
});
var SubmitForm = React.createClass({
handleSubmit: function(e) {
//??
},
render: function() {
return (
<form className="actionForm" onSubmit={this.handleSubmit}>
<input type="submit" value="Run" />
</form>
);
}
});
ReactDOM.render(
<ActionBox data={data} />,
document.getElementById('content')
);
I found a solution that works I don’t think it’s the best way but maybe it will help other.
I loop thought the element to get the value- I believe there is a better way of doing it with react.
var data = [
{ Label: "Action 1", IsChecked: false, Name: "a1" },
{ Label: "Action 2", IsChecked: false, Name: "a2" },
{ Label: "Action 3", IsChecked: false, Name: "a3" }
];
handleCommentSubmit: function () {
var data = new FormData();
var inputs = document.getElementsByName('mycheckbox');
for (var i = 0; i < inputs.length; i++) {
var name = inputs.item(i).value;
var ischecked = inputs.item(i).checked;
data.append(name, ischecked);
}
var xhr = new XMLHttpRequest();
xhr.open('post', this.props.submitUrl, true);
xhr.send(data);
},

Meteor: How can I restrict user on a chat?

Im working on a project and my last task is to implement publish and subscribe to prevent users seeing conversations they were not involved in. We were given an example code and I notice a filter on the router.
Router.route('/chat/:_id', function () {
// the user they want to chat to has id equal to
// the id sent in after /chat/...
var otherUserId = this.params._id;
// find a chat that has two users that match current user id
// and the requested user id
var filter = {$or:[
{user1Id:Meteor.userId(), user2Id:otherUserId},
{user2Id:Meteor.userId(), user1Id:otherUserId}
]};
var chat = Chats.findOne(filter);
if (!chat){// no chat matching the filter - need to insert a new one
chatId = Chats.insert({user1Id:Meteor.userId(), user2Id:otherUserId});
}
else {// there is a chat going already - use that.
chatId = chat._id;
}
if (chatId){// looking good, save the id to the session
Session.set("chatId",chatId);
}
this.render("navbar", {to:"header"});
this.render("chat_page", {to:"main"});
});
I thought the filter should be on publish and then subscribe. Here is what I have now.
My HTML
<template name="chat_page">
<h2>Type in the box below to send a message!</h2>
<div class="row">
<div class="col-md-12">
<div class="well well-lg">
{{#each recentMessages}}
{{> message}}
{{/each}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
{{#if currentUser}}
<form class="new-message">
<input class="input" type="text" name="text" placeholder="type a message here...">
<button class="btn btn-default">Send</button>
</form>
{{/if}}
</div>
</div>
</template>
<!-- simple template that displays a message -->
<template name="message">
<div class = "container">
<div class = "row">
<div class = "username">
<img src="/{{avatar}}" class="avatar_img" >
{{username}}
said: {{messageText}}
</div>
</div>
</div>
</template>
Server Side
Meteor.startup(function () {
if (!Meteor.users.findOne()){
for (var i=1;i<9;i++){
var email = "user"+i+"#test.com";
var username = "user"+i;
var avatar = "ava"+i+".png"
console.log("creating a user with password 'test123' and username/ email: "
+ email);
Meteor.users.insert({
profile:{username:username, avatar:avatar},
emails: [{address:email}],
services:{
password:{"bcrypt" : "PASSWORD REMOVED"}}});
}
}
});
Meteor.publish("messages", function (userId) {
return Messages.find();
});
Meteor.publish("userStatus", function() {
return Meteor.users.find({ "status.online": true });
});
Meteor.publish("userData", function(){
if(this.userId) {
return Meteor.users.find({_id: this.userId},{
fields: {'other':1, 'things': 1}});
} else {
this.ready();
}
return Meteor.users.find({ "status.online": true })
});
Client Side
Meteor.subscribe("messages");
Meteor.subscribe("userStatus");
Meteor.subscribe("userData");
// set up the main template the the router will use to build pages
Router.configure({
layoutTemplate: 'ApplicationLayout'
});
// specify the top level route, the page users see when they arrive at the site
Router.route('/', function () {
console.log("rendering root /");
this.render("navbar", {to:"header"});
this.render("lobby_page", {to:"main"});
});
Router.route('/chat/:_id', function () {
this.render("navbar", {to:"header"});
this.render("chat_page", {to:"main"});
});
///
// helper functions
///
Template.message.helpers({
userName: function() {
var userId = this.userId;
var user = Meteor.users.findOne(userId);
var username = user && user.profile && user.profile.username;
var avatar = user && user.profile && user.profile.avatar;
return {
username: username,
avatar: avatar
}
}
})
Template.available_user_list.helpers({
users:function(){
return Meteor.users.find();
}
})
Template.available_user.helpers({
getUsername:function(userId){
user = Meteor.users.findOne({_id:userId});
return user.profile.username;
},
isMyUser:function(userId){
if (userId == Meteor.userId()){
return true;
}
else {
return false;
}
}
})
Template.chat_page.helpers({
recentMessages: function () {
if (Session.get("hideCompleted")) {
return Messages.find({checked: {$ne: true}}, {sort: {createdAt: -1}});
} else {
return Messages.find({}, {sort: {createdAt: 1}});
}
},
hideCompleted: function () {
return Session.get("hideCompleted");
},
incompleteCount: function () {
return Tasks.find({checked: {$ne: true}}).count();
}
});
Template.chat_page.events({
// this event fires when the user sends a message on the chat page
'submit .new-message':function(event){
console.log(event);
event.preventDefault();
var text = event.target.text.value;
// stop the form from triggering a page reload
event.target.text.value = "";
// see if we can find a chat object in the database
// to which we'll add the message
Meteor.call("sendMessage", text);
},
});
Collections
Messages = new Mongo.Collection("messages");
Shared-Methods
Meteor.methods({
sendMessage: function (messageText) {
if (! Meteor.userId()) {
throw new Meteor.Error("not-authorized");
}
Messages.insert({
messageText: messageText,
createdAt: new Date(),
username: Meteor.user().profile.username,
avatar: Meteor.user().profile.avatar,
});
}
});

Unable to display data from database

I am building a forum with Meteor and would like to display comments to answers. And the answers are on the same page as an individual question. I am able to save the comments once submitted (I can check the mongo database and I see that I am successfully submitting comments), but I'm not able to display them using templates. I would think the problem has something to do with publications and subscriptions, but I can't locate the error. Below are the relevant snippets of code.
answer_item.js
Template.answerItem.helpers({
submittedText: function() {
return this.submitted.toString();
},
comments: function() {
return Comments.find({answerId: this._id});
}
});
answer_item.html
<template name="answerItem">
...
<ul class="comments">
{{#each comments}}
{{> commentItem}}
{{/each}}
</ul>
...
</template>
comment_item.html
<template name="commentItem">
<li>
<h4>
<span class="author">{{author}}</span>
<span class="date">on {{submitted}}</span>
</h4>
<p>{{body}}</p>
</li>
</template>
comment_item.js
Template.commentItem.helpers({
submittedText: function() {
return this.submitted.toString();
}
});
lib/collections/comment.js
Comments = new Mongo.Collection('comments');
Meteor.methods({
commentInsert: function(commentAttributes) {
check(this.userId, String);
check(commentAttributes, {
answerId: String,
body: String
});
var user = Meteor.user();
var answer = Answers.findOne(commentAttributes.answerId);
if (!answer)
throw new Meteor.Error('invalid-comment', 'You must comment on an answer');
comment = _.extend(commentAttributes, {
userId: user._id,
author: user.username,
submitted: new Date()
});
Answers.update(comment.answerId, {$inc: {commentsCount: 1}});
comment._id = Comments.insert(comment);
return comment._id
}
});
router.js
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
notFoundTemplate: 'notFound',
waitOn: function() {
return [Meteor.subscribe('notifications')]
}
});
QuestionsListController = RouteController.extend({
template: 'questionsList',
increment: 5,
questionsLimit: function() {
return parseInt(this.params.questionsLimit) || this.increment;
},
findOptions: function() {
return {sort: this.sort, limit: this.questionsLimit()};
},
subscriptions: function() {
this.questionsSub = Meteor.subscribe('questions', this.findOptions());
},
questions: function() {
return Questions.find({}, this.findOptions());
},
data: function() {
var self = this;
return {
questions: self.questions(),
ready: self.questionsSub.ready,
nextPath: function() {
if (self.questions().count() === self.questionsLimit())
return self.nextPath();
}
};
}
});
NewQuestionsController = QuestionsListController.extend({
sort: {submitted: -1, _id: -1},
nextPath: function() {
return Router.routes.newQuestions.path({questionsLimit: this.questionsLimit() + this.increment})
}
});
FollowedQuestionsController = QuestionsListController.extend({
sort: {follows: -1, submitted: -1, _id: -1},
nextPath: function() {
return Router.routes.followedQuestions.path({questionsLimit: this.questionsLimit() + this.increment})
}
});
Router.route('/', {
name: 'home',
controller: NewQuestionsController
});
Router.route('/new/:questionsLimit?', {name: 'newQuestions'});
Router.route('/followed/:questionsLimit?', {name: 'followedQuestions'});
Router.route('/questions/:_id', {
name: 'questionPage',
waitOn: function() {
return [
Meteor.subscribe('singleQuestion', this.params._id),
Meteor.subscribe('answers', this.params._id),
Meteor.subscribe('comments', this.params._id)
];
},
data: function() { return Questions.findOne(this.params._id); }
});
Router.route('/questions/:_id/edit', {
name: 'questionEdit',
waitOn: function() {
return Meteor.subscribe('singleQuestion', this.params._id);
},
data: function() { return Questions.findOne(this.params._id); }
});
Router.route('/submit', {name: 'questionSubmit'});
var requireLogin = function() {
if (! Meteor.user()) {
if (Meteor.loggingIn()) {
this.render(this.loadingTemplate);
} else {
this.render('accessDenied');
}
} else {
this.next();
}
}
Router.onBeforeAction('dataNotFound', {only: 'questionPage'});
Router.onBeforeAction(requireLogin, {only: 'questionSubmit'});
server/publications.js
Meteor.publish('comments', function(answerId) {
check(answerId, String);
return Comments.find({answerId: answerId});
});
It looks like you need to run a separate query in your comment publication, to get a list of all of the answers for the given question, then use the results of that query to get a list of all the comments for all of the answers.
Meteor.publish('comments', function(questionId) {
check(questionId, String);
var answerIds = _.pluck(Answers.find({'questionId': questionId}, {fields: {_id: 1}}).fetch(), '_id');
return Comments.find({answerId: {$in: answerIds});
});
EDIT
I have a similar feature within an app that I'm working on now, with the same issue you were running into. I spent a few hours on it yesterday and came to the conclusion that the issue has to do with the fact that the _.pluck statement converts the results from the Answers cursor to an array, which prevents the publish function from being reactive.
After looking into several solutions the best one I found was the publish composite package. The syntax is a little verbose, but it gets the job done. To make it all work properly you need to merge all of the publish functions for the question, answers, and comments all into one publish function. Under the covers it creates observeChanges watchers on each of the answers under the question, so it can be reactive.
Meteor.publishComposite('question', function(questionId) {
return {
find: function() {
return Questions.find({_id: questionId});
},
children: [
{
find: function(question) {
return Answers.find({questionId: question._id});
},
children: [
{
find: function(answer, question) {
return Comments.find({answerId: answer._id});
}
}
]
}
]
}
});

UI helper function does not have the subscription data in Meteor

I am fairly new to Meteor.
I have a template helper function which requires to work with data I am publishing from the server side. When the page loads, the value for profile below is undefined. But after that when I execute the same code snippet from browser's console, it works just fine. From what I understand, the template helper is being executed before the data is published. How can I wait until the data is published to run the UI helper?
Here is relevant code.
Helper Function
Template.header.helpers({
me: function() {
var user = Meteor.users.findOne(Meteor.userId());
if (user) {
return Profiles.findOne({
spid: user.profile.spid
});
}
return null;
}
});
HTML Template
<template name="header">
<header class="ui fixed inverted menu">
{{> thumb user=me}}
</header>
</template>
Thumbnail Template
<template name="thumb">
{{#with user}}
<div class="thumb">
<div class="text" style="background-color:{{color}}">
{{initials name}}
</div>
<div class="pic" style="background-image:url('{{pic}}')"></div>
</div>
{{/with}}
</template>
Publications
Meteor.publish('profiles', function() {
return Profiles.all();
});
Meteor.publish('departments', function() {
return Departments.all();
});
Meteor.publish('requestServiceIds', function() {
return Requests.getServiceIds();
});
Meteor.publish('relevantServices', function() {
return Services.getRelevant(this.userId, 5);
});
Router
Router.configure({
layoutTemplate: 'main',
waitOn: function() {
Deps.autorun(function() {
Meteor.subscribe('profiles', Partitioner.group());
Meteor.subscribe('departments', Partitioner.group());
});
}
});
Router.onBeforeAction(function() {
if (this.route.getName() === 'not-authorized') return this.next();
if (!Meteor.userId() || !Cookie.get('TKN')) {
this.render('login');
} else {
this.next();
}
});
Router.route('/', {
name: 'home',
waitOn: function() {
Deps.autorun(function() {
Meteor.subscribe('requestServiceIds', Partitioner.group());
Meteor.subscribe('relevantServices', Partitioner.group());
});
}
});
---
UPDATE 1
I updated the the router a bit. But it did not seem to have had made any difference.
Router.configure({
layoutTemplate: 'main',
waitOn: function() {
// Deps.autorun(function() {
// Meteor.subscribe('profiles', Partitioner.group());
// Meteor.subscribe('departments', Partitioner.group());
// });
return [
Meteor.subscribe('profiles', Partitioner.group()),
Meteor.subscribe('departments', Partitioner.group())
];
}
});
Router.route('/', {
name: 'home',
waitOn: function() {
// Deps.autorun(function() {
// Meteor.subscribe('requestServiceIds', Partitioner.group());
// Meteor.subscribe('relevantServices', Partitioner.group());
// });
return [
Meteor.subscribe('requestServiceIds', Partitioner.group()),
Meteor.subscribe('relevantServices', Partitioner.group())
];
}
});
Create a dumb loading template such as this one (using font awesome):
<template name="loading">
<div class="loading">
<i class="fa fa-circle-o-notch fa-4x fa-spin"></i>
</div>
</template>
And try replacing your Router.configure() part with something like this:
Router.configure({
layoutTemplate: 'main',
action: function() {
if(this.isReady()) { this.render(); } else {this.render("loading");}
},
isReady: function() {
var subs = [
Meteor.subscribe('profiles', Partitioner.group());
Meteor.subscribe('departments', Partitioner.group());
];
var ready = true;
_.each(subs, function(sub) {
if(!sub.ready())
ready = false;
});
return ready;
},
data: function() {
return {
params: this.params || {},
profiles: Profiles.find(),
departments: Departments.find()
};
}
}
});
I guess that could be achieved using waitOn, but since your way does not work, I give you a working recipe I use everyday. Code inspired from meteor Kitchen generated code.
To answer your comments:
Regarding the Action not being triggered, it might be because we tried to put in inside the Router.configure. I don't do it that way, here are some details on how I implement it.
First, I set a controller for each route inside a router.js file (where I have my Router.configure() function too. It looks like that:
Router.map(function () {
this.route("login", {path: "/login", controller: "LoginController"});
// other routes
}
Next, I create a controller that I store in the same folder than my client view template. It looks like that:
this.LoginController = RouteController.extend({
template: "Login",
yieldTemplates: {
/*YIELD_TEMPLATES*/
},
onBeforeAction: function() {
/*BEFORE_FUNCTION*/
this.next();
},
action: function() {
if(this.isReady()) { this.render(); } else { this.render("loading"); }
/*ACTION_FUNCTION*/
},
isReady: function() {
var subs = [
];
var ready = true;
_.each(subs, function(sub) {
if(!sub.ready())
ready = false;
});
return ready;
},
data: function() {
return {
params: this.params || {}
};
/*DATA_FUNCTION*/
},
onAfterAction: function() {
}
});
So this action function is working when I extend a route using a controller. Maybe it will solve your issue.
For completeness sake, here is how my Router.configure() looks like:
Router.configure({
templateNameConverter: "upperCamelCase",
routeControllerNameConverter: "upperCamelCase",
layoutTemplate: "layout",
notFoundTemplate: "notFound",
loadingTemplate: "loading",
//I removed the rest because it is useless.
});

Resources