Meteor Merge two cursors data of same collection - meteor

I have a strange problem here.
I want to merger two cursors data into single cursor of same collection.
Here is my code
{{#each friendsPolls.data}}
{{#if username}}
{{#each questions}}
{{question}}
{{/each}}
{{/if}}
{{/each}}
app.js
Questions:function(){
Meteor.call('isFbExists', this.username, function (error, result) {
if(result) {
var ee=Ques_Coll.find({owner:result._id});
}
})
}
How can I return the cursor to my template, where it substitutes the {{question}} value.
This function is called many times(length fb friends). Each time when this calls server method it checks whether the user exists in my database or not.
If he already exists then I search for his documents and want to display them
However, if I do like above the data is override and it returns the last user results only.
So,each time it search in collection I want to append that cursor to existing one

Related

Vue.js - cannot read property even though the object exists

I used vue-resource to fetch data from firebase. basically when I loop through each object under the orders directory, I match the userId of that object, find the object under the users directory, and save it on my local array as a nested object (userData) along with the retrieved orders objects. here's my code:
//retrieve objects from orders
this.$http.get('https://nots-76611.firebaseio.com/Orders.json').then(function(data){
return data.json();
}).then(function(data){
var ordersArray = [];
for (let key in data){
data[key].id = key;
data[key].measurementsArray = Object.entries(data[key].measurements).sort();
//retrieve a specific user based on the userId of each orders object
this.$http.get('https://nots-76611.firebaseio.com/Users/' + data[key].userId + '.json').then(function(userdata){
return userdata.json();
}).then(function(userdata){
data[key].userData = userdata; //store the object
});
ordersArray.push(data[key]); //pass the object along the userData
}
this.orders = ordersArray;
console.log(this.orders);
});
the object structured shown in the console is perfectly fine:
but when I try to, access the nested object in the dom via {{ order.userData.Address }}:
<tr v-for="order in orders"
<dialog class="mdl-dialog" ref="userDialog">
<h4 class="mdl-dialog__title">Customer's Information</h4>
<div class="mdl-dialog__content">
{{ order.userData.Address }}
</div>
<div class="mdl-dialog__actions">
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect" v-on:click="closeUser(ndx)">
OK
</button>
</div>
</dialog>
</tr>
it says Error in render function: "TypeError: Cannot read property 'Address' of undefined". I don't understand it because I can easily retrieve the properties in the measurements object (which is also a nested object)
did I messed up in the retrieval process? or in the DOM rendering?
EDIT:
I tried using {{ order }} instead of {{ order.userData.Address }} and it seems like the userData object was not stored in each of the orders object
Also, I noticed something strange about how the userData object is shown differently from the measurements object which is originally stored there along with the parent object:
There are two primary issues here.
First, the data is retrieved asynchronously which means, it does not exist when the component is first rendered. In the template you use
order.userData.Address
There is a point in time when there are orders but there is no userData, because the data has not been retrieved yet. That being the case, Vue attempts to render the orders, and tries to render order.userData.Address, but there is no userData. That's why you get the error, "Cannot read property 'Address' of undefined". In order to fix that, you should use a guard to make sure to only try to render Address when it is available.
{{orders.userData && orders.userData.Address}}
That will prevent the error.
There is a secondary error that you probably have not yet noticed. userData is not reactive. The reason for this is because Vue cannot detect when properties are added to an object after that object has been added to data. The code is setting userData like so:
data[key].userData = userdata;
and this occurs after the orders array has been added to the Vue because it is performed in an asynchronous call. Instead, you should use,
this.$set(data[key], 'userData', userdata)

Where can I store a JSON document so that it can be accessed from a template helper multiple times?

In my code, I am trying to access a collection that stores information about books. I'm looping over an array that only stores the ID of each book. Then I am using that ID to query the book from a collection called Books, which stores complete information for each book
Template.myBorrows.helpers({
storeInSession:function(ilendbooksId) {
console.log("storeInSession is called");
var currentBorrowBook = Books.findOne({_id: ilendbooksId});
Session.setAuth('currentBorrowBook' , currentBorrowBook);
},
getAuthor: function() {
var currentBorrowBook = Session.get('currentBorrowBook');
return currentBorrowBook.ItemAttributes[0].Author[0];
},
});
I am querying the book document by the book's _id in the Books collection. Then I am storing it in a session, then calling appropriate methods to get information. The only problem is that I have to do this for an array of books, so every time the previous document in the Session gets overwritten and all my data on my page changes to the most current Session document. How and where can I store each book's document and ensure that the correct information is displayed without it updating to the most current Session doc?
To answer your comment then, you have an array of document _ids and you want to fetch the document in your templates.
html:
<template name="myTemplate">
{{#each array}}
{{#with doc}}
Author: {{author}}
{{/with}}
{{/each}}
</template>
js:
Template.myTemplate.helpers({
array(){ return theArrayOfIdsThatYouveDefined; },
doc(){ return Books.findOne(this); }
});
Inside the {{#each array}} loop this will be an element of the array. The doc helper simply looks up a book from the Books collection and returns it. Now inside the {{#with doc}} block the data context will be a book object.
No session variables or method calls required.

Meteor: How do I adjust iron router return data based on search query?

I have an app where users can take notes.
In the html page I iterate over each note like so:
<div id="notes-container" class="notes">
{{each notes}}
{{> note}}
{{/each}}
</div>
and in my router file I return the data like so:
#route: 'notes'.
path: '/notes/:_id',
data: ->
notes = Notes.find
threadId: #params._id
trash:
$exists: false
,
sort:
date: -1
All is typical meteor stuff so far. But I am confused now about how to adjust the data that is iterated on in the html page.
Each notes has a array field for tags like tags: ['apple' ,'red', 'green']
What if the user wants to return all notes with the tag 'red'. So there is a input box on the site the user enters a tag and presses enter.
How can I adjust the data that is sent to the page so queries mongodb to return all notes with tag red? I know how to write the query I am not sure how to set this up though in meteor.
One way I tried to do it is called the same route with query paramters like: '/notes/326363235474?tags=apple'
And in iron router I can look for query parameters and return the right set of documents but then when I call the original route again to clear the search, it does not load all of the original documents again.
Any suggestion on how I can set this up? Thanks
the data function simply needs to return the data you want available within the template context, if I'll define this function to a certain route:
data: ->
return Drawing.findOne
_id: window._drawing_id
I will have that data in my "this" object when proccessing that template.

Meteor: How to make a helper function reactive?

I'm trying to get a helper to re-run and return the updated collection whenever this collection is updated.
For example:
Template.imagegallery.myimages = function() {
return Images.find({owner: Meteor.userId()}).fetch();
}
When I add data to the Images via a Meteor.call on the server side, my collection updates locally on the client, but the helper function does not re-run and the images don't update.....
any idea what i need to do to put the return collection from the helper object into a re-active context?
Return a cursor instead of a array:
Helper:
Template.imagegallery.myimages = function() {
return Images.find({owner: Meteor.userId()});
}
Template:
<template name="imagegallery">
{{#each myimages}}
!!!DOSTUFF!!!
{{/each}}
</template>
Fetch breaks reactivity in almost all cases. Because when you use fetch the Blaze only receives a array. So Blaze never creates the dependencies required for reactivity because it doesn't know that is data coming from a collection as that information is lost when you use fetch.
*Blaze is meteor's templating system

How do I delete or remove Session variables?

Meteor has a Session that provides a global object on the client that you can use to store an arbitrary set of key-value pairs. Use it to store things like the currently selected item in a list.
It supports Session.set, Session.get and Session.equals.
How do I delete a Session name, value pair? I can't find a Session.delete(name) ?
[note: this answer is for Meteor 0.6.6.2 through at least 1.1.0.2]
[edit: updated to also explain how to do this while not breaking reactivity. Thanks to #DeanRadcliffe, #AdnanY, #TomWijsman, and #MikeGraf !]
The data is stored inside Session.keys, which is simply an object, so you can manually delete keys:
Session.set('foo', 'bar')
delete Session.keys['foo']
console.log(Session.get('foo')) // will be `undefined`
To delete all the keys, you can simply assign an empty object to Session.keys:
Session.set('foo', 'bar')
Session.set('baz', 'ooka!')
Session.keys = {}
console.log(Session.get('foo')) // will be `undefined`
console.log(Session.get('baz')) // will be `undefined`
That's the simplest way. If you want to make sure that any reactive dependencies are processed correctly, make sure you also do something like what #dean-radcliffe suggests in the first comment. Use Session.set() to set keys to undefined first, then manually delete them. Like this:
// Reset one value
Session.set('foo', undefined)
delete Session.keys.foo
// Clear all keys
Object.keys(Session.keys).forEach(function(key){ Session.set(key, undefined); })
Session.keys = {}
There will still be some remnants of the thing in Session.keyDeps.foo and Session.keyValueDeps.foo, but that shouldn't get in the way.
Session.set('name', undefined) or Session.set('name', null) should work.
The disadvantage with using delete Session.keys['foo'] is that your template will not hot reload if the session key holds an array. For instance, if you are doing
Template.mytempl.helpers({
categories: function() {
return Session.get('srch-categories')
}
})
and in your template
{{#if categories}}
{{#each categories}}
{{this}}
{{/each}}
{{/if}}
And categories is an array, if you delete the session key, your template will continue to display the last value of categories.

Resources