Meteor.publish on server doesn't show new documents on client - javascript

The problem is the next code on server:
Meteor.publish(null , function() {
let events = [];
Groups.find({participants: this.userId}).forEach(function(item) {
events.push(item.latestEvent);
});
return Events.find({_id: {$in: events}});
});
doesn't provide possibility to see new documents on the client > Events.find().fetch()
without reloading the page.
Both collection are in the lib folder:
Groups = new Mongo.Collection('groups');
Events = new Mongo.Collection('events');
I'm pretty sure the issue is in reactive source of data, but still cannot fix it.
Thank You for help!

Yes, you are right: only Events collection is reactive. There is simple way to solve it by using publish-composite package:
Meteor.publishComposite(null, {
find(){
return Groups.find({participants: this.userId});
},
children: [{
find(group){
return Events.find({_id: {$in: group.latestEvent}});
}
}]
});
But this solution has one disadvantage: Groups documents are published as well. So, probably you should exclude some fields from it.

Related

Issue with multiple subscriptions on one publication

I have a page that generates a series of post templates, each of which subscribes to a single publication. I'm running into an issue where passing the post ID to my publication does not return any results. Can anyone help me figure out what's wrong?
I have tried using console.log() inside onCreated (both inside and outside of the autorun) to make sure that my IDs are correctly generated and have also tried other query values (such as {$exists:true}) to ensure that my query is working.
// client
CommentSubs = new SubsManager();
Template.post.onCreated(function() {
var self = this;
self.ready = new ReactiveVar();
self.autorun(function() {
var commentParent = this._id;
var handle = CommentSubs.subscribe('comments', commentParent);
self.ready.set(handle.ready());
});
});
// server
Meteor.publish("comments", function (commentParent) {
return Posts.find({commentParent: commentParent}, {sort: {createdAt: 1}});
});
I am new to meteor so perhaps I am missing something that should be obvious.

Get specific value from Firebase JSON tree based on value

I am writing a Javascript web app using Firebase. If I have data like this in my JSON tree:
users
session1
screenname:Bill
session2
screenname:Steve
...and I know the session number, how can I grab the "name" of the user? I have tried this:
valUsers.child('session1').child('screenname').once('value', function(data){
console.log(data);
});
But that does not seem to work. I'm guessing I have a syntax issue?
You were pretty close, but needed to use DataSnapshot.val() as shown below to access the point you want.
var ref = new Firebase('yourfirebaselocation/users');
var sessionNum = 'session1';
ref.child(sessionNum + '/screenname').once('value', function(dataSnapshot) {
var specificScreenname = specificPoint.val();
}
When working with Firebase, you may want to also explore working with Promise objects. This would allow you to create some repeatable functions that can reuse your reference on multiple locations and also give Firebase time to respond to your query.
var ref = new Firebase('yourfirebaselocation/users');
function getUser(theRef, location) {
return new Promise(
function(resolve, reject) {
theRef.child(location).once('value', function(dataSnapshot) {
resolve(dataSnapshot);
});
});
}
getUser(ref, specificlocationvariable).then( function(val) {
specificScreenname = val.val();
});
You don't specify other than 'JavaScript' so do keep in mind that Promises are an ECMAScript 6 proposal with some compatibility issues, but a lot of the JS frameworks have an implementation for it that smooth that issue (Angular, Ember, etc).

Umbraco 7: How can I refresh the tree view in my custom section?

I have created a custom section in umbraco to manage some data in an SQL database.
I can edit items OK but when adding I need to refresh the page to see my new row in the custom tree on the left.
How can I cause a refresh of my custom tree using AngularJS? My tree is called "clients".
I have tried debugging the code and looking at the source to find the event but I can't seem to work out how to do it.
Is there a method I can call on the umbTreeDirective somehow? Or an event to subscribe to?
I am fairly new to AngularJS and am struggling a little.
You're looking for the navigationService.
This line is example of a syncTree call:
navigationService.syncTree({ tree: 'clients', path: content.path, forceReload: false, activate: true });
Here's a contrived, spaghetti promised but full example:
angular.module("umbraco")
.directive('nowplaying', ['navigationService', 'contentResource', 'contentEditingHelper', function (navigationService, contentResource, contentEditingHelper) {
//spaghetti example to create new document
contentResource.getScaffold(parentId, alias)
.then(function (scaffold) {
var myDoc = scaffold;
myDoc.name = name;
//we have minimum to publish
contentResource.publish(myDoc, true, [''])
.then(function (content) {
$scope.newlyCreatedNode = content;
//Sync ('refresh') the tree!
navigationService.syncTree({ tree: 'clients', path: content.path, forceReload: false, activate: true });
});
});
}]);
All of the Belle documentation lives here. -I'm not sure it's actively maintained, i can say for certain that one or two signatures have changed since it was first posted. That aside, it's the best resource i know of to interact with all the umbraco exposed modules and services.

Meteor Leaderboard example: resetting the scores

I've been trying to do Meteor's leaderboard example, and I'm stuck at the second exercise, resetting the scores. So far, the furthest I've got is this:
// On server startup, create some players if the database is empty.
if (Meteor.isServer) {
Meteor.startup(function () {
if (Players.find().count() === 0) {
var names = ["Ada Lovelace",
"Grace Hopper",
"Marie Curie",
"Carl Friedrich Gauss",
"Nikola Tesla",
"Claude Shannon"];
for (var i = 0; i < names.length; i++)
Players.insert({name: names[i]}, {score: Math.floor(Random.fraction()*10)*5});
}
});
Meteor.methods({
whymanwhy: function(){
Players.update({},{score: Math.floor(Random.fraction()*10)*5});
},
}
)};
And then to use the whymanwhy method I have a section like this in if(Meteor.isClient)
Template.leaderboard.events({
'click input#resetscore': function(){Meteor.call("whymanwhy"); }
});
The problem with this is that {} is supposed to select all the documents in MongoDB collection, but instead it creates a new blank scientist with a random score. Why? {} is supposed to select everything. I tried "_id" : { $exists : true }, but it's a kludge, I think. Plus it behaved the same as {}.
Is there a more elegant way to do this? The meteor webpage says:
Make a button that resets everyone's score to a random number. (There
is already code to do this in the server startup code. Can you factor
some of this code out and have it run on both the client and the
server?)
Well, to run this on the client first, instead of using a method to the server and having the results pushed back to the client, I would need to explicitly specify the _ids of each document in the collection, otherwise I will run into the "Error: Not permitted. Untrusted code may only update documents by ID. [403]". But how can I get that? Or should I just make it easy and use collection.allow()? Or is that the only way?
I think you are missing two things:
you need to pass the option, {multi: true}, to update or it will only ever change one record.
if you only want to change some fields of a document you need to use $set. Otherwise update assumes you are providing the complete new document you want and replaces the original.
So I think the correct function is:
Players.update({},{$set: {score: Math.floor(Random.fraction()*10)*5}}, {multi:true});
The documentation on this is pretty thorough.

Backbone infinite loop when creating models

I'm doing something pretty standard, I think.
Model:
app.model.Todo = Backbone.Model.extend({
defaults: {
task: ''
, completed: 0
, attachments: []
, note: ''
}
});
Collection:
var Todos = Backbone.Collection.extend({
model: app.model.Todo
, localStorage: new Store('Todos')
, incomplete: function () {
return this.filter(function (todo) {
return !todo.get('completed')
});
}
, complete: function () {
return this.filter(function (todo) {
return todo.get('completed')
});
}
, comparator: function(todo) {
return todo.get('order');
}
});
app.collection.Todos = new Todos();
Then, if I just do:
app.collection.Todos.create({task: 'hi'});
app.collection.Todos.create({task: 'hi'});
The 2nd one never works. I get an infinite loop (too much recursion on Firefox and stack_overflow on Chrome).
I'm really at a loss. I commented out all events as well.
Appears it spins out of control here in backbone:
// Return a copy of the model's `attributes` object.
toJSON: function(options) {
return _.clone(this.attributes);
},
UPDATE: If I add id: 0 or whatever id to the model the error stops, but if I give it a custom ID (i.e. new Date().getTime() the error happens again. It's like whenever I create a unique item it blows up.
UPDATE 2:
var todo = new gator.model.Todo({task: actionbarVal});
gator.collection.Todos.add(todo);
gator.collection.Todos.sync('create', todo);
Doing the above kinda works, and for what I need it for it works, but it's really bad. It's bad because every single time we do a new add and sync it calls toJSON 1 time for every time add and sync has been called on this page load. So, if you add 3 items, you get 6 toJSON calls (1 for the first, 2 for the second, 3 for the third). Also, it's not as clean. I also noticed in the toJSON call in backbone this.attributes with create was correct the first time. The 2nd time it was like this.attributes == backbone or something. Very, very strange. It had all the methods of Backbone. It was as if clone did a deep clone or something.
You have a mismatch between your version of Backbone (v0.9.9) and the version of the localstorage add-on. Be sure to get the latest version of the localstorage add-on from the Backbone repo and it will fix this problem.
I eventually fixed it by reverting back to 0.9.2 of Backbone, thanks to Derick Bailey. My attempts of using the latest localStorage add-on didn't seem to fix it. Maybe I was using a different source? I was using develop of this:
https://github.com/jeromegn/Backbone.localStorage

Categories