Meteor prefetch data - meteor

On Meteor, I'd like to prefetch data. I know this is normally automatically done. But there is a small wait for some action.
For example, I put a jquery event and change a session variable. Minimongo don't have that datas and have to fetch them.
I'd like to make an animation during which I'm fetching data and at the end of the animation change the templates.
Is it possible? How mould you do that?
Thanks in advance.

The only way minimongo won't have your data is when your subscription changes. So you could do
Edit: Clearing it up
Meteor.autosubscribe(function() {
//ADD LOADING TO PAGE HERE (1)
page = Session.get('paging')
Session.set('Sess1', true)
Meteor.subscribe('testdata', page, function() {
//remove loading to page here (2)
Session.set('Sess1', false)
});
});
For the template it doesn't need to change. You could set a Session at (1) and set another at (2).
So
<template name="test">
{{#if Sess1}}
might be loading here
{{else}}
display the data here
{{/if}}
</template>

Related

How to prevent firebase-query element to updating the data

I am using polymer and firebase to create a web app. To get a list in the database, I am using the "firebase-query" element of polymerfire.
Now, the list of items I am getting from the database is posts that people are posting on my app. Now I have the firebase-query element like this:
<firebase-query
id="query"
path="/posts"
limit-to-last="15"
data="{{posts}}">
</firebase-query>
and I have dom-repeat template tag to display the posts like this
<template is="dom-repeat" items="[[posts]]" as="post">
<div>[[post.content]]</div>
</template>
Now, if I have bunch of people posting a lot of contents at once, this list would be updating every second, and it would be hard to read.
Is there a way to prevent firebase-query element to stop updating once the initial load is complete, and possibly updating again when I call a certain function?
I tried to add a disabled attribute, but that just deletes whatever is inside the data attribute ({{posts}} in my case), so when disabled is set, nothing shows up on the screen.
I am not familiar with firebase-query, but you can do simple trick. On property posts set observer function.
posts: {
Type: Array,
value: function(){return []},
observer: "debouncePosts"
}
then in js you can define debounce function where I set, for example, 10 000 miliseconds (10 seconds) and called some callback function where I set this.posts to currentPosts property which will be rendered in template.
debouncePosts: function(data) {
this.debounce("debouncePost", function(){
this.set("currentPosts", this.posts);
}.bind(this), 10000)
}
and html template will be like:
<template is="dom-repeat" items="[[currentPosts]]" as="post">
<div>[[post.content]]</div>
</template>
documentation to debounce: https://www.polymer-project.org/1.0/docs/api/Polymer.Base#method-debounce
If you like to do it in different way like update data whenever user presses update, it's really easy now for you. Just set on-tap on some button and then in function you will do something like this.set("currentPosts", this.posts)

Wait for Meteor.user() to completely load before template renders

This has been asked before however, I don't feel I've seen a suitable answer. I'm currently using {{ #if currentUser.emails.[0].verified }} show data {{else}} please verify email {{/if}} on the layout template check whether or not the user has verified their email. In this scenario, I get a flicker between the screens if the user has registered because meteor.user() hasn't loaded completely so currentUser.emails.[0].verified returns null and changes to true once it has loaded completely.
Is there a way I can wait for Meteor.userId to completely load before the template renders without using delay?
The meteor embedded "currentUser" helper can let you know when the user collection is ready:
{{#if currentUser}}
// Do my stuff
{{else}}
Checking... // You can also show a spinner image or GIF here
{{/if}}
You can force the Template.subscriptionsReady to wait for the Meteor.user() data (so that when the Template.subscriptionsReady is true, the currentUser logic is also up-to-date and won't change) by adding a stub subscription.
I added the following Subscription and then subscribed to this from the template:
Meteor.publish('userWait', function () {
return null;
});
Here's a more detailed description of why this issue was popping up:
When loading a template, if you're only relying native handler for currentUser - then currentUser will always initially load false (in the template logic) and then will load true once the data load is complete.
Adding logic to show a loading state that relies on Template.subscriptionsReady will only work if there is an additional Subscription for the template (Template.subscriptionsReady doesn't acknowledge the automatic subscriptions for the user data).
For me, this meant that the internal pages will always prompt a login before realizing that the user was already logged in ... which was an ugly UX.
Once I added a Subscription to the template, even though it returned nothing, then Template.subscriptionsReady would wait until Meteor.user() data was available before returning as true.
Typically, you can use Template.subscriptionsReady in your Template to wrap code that depends upon subscribed data. Since Meteor handles the publish/subscribe of currentUser automatically, I'm not sure if this method will work or not. Give it a try and let me know.
Example.
{{#if Template.subscriptionsReady}}
{{ #if currentUser.emails.[0].verified }} show data {{else}} please verify email {{/if}}
{{/if}}
What I have found to work well for me is to subscribe to the user in the wait in a waitOn function in iron router:
Router.route('/',{
waitOn: [
function() {
if (!Meteor.userId()) {
Router.go("/login");
}
return Meteor.subscribe('currUser');
},
],
...
})

Meteor infinite scroll : prevent subscribe to rerender elements

I'm implementing an infinite scroll on Meteor in order to display a grid of pictures linked to a large collection.
When the user is at the end of the page I subscribe to more elements and I increase the number of pictures displayed (through my template.helper).
//SERVER
Meteor.publish('generalMusics', function(limit){
return Musics.find({}, {limit: limit});
});
//CLIENT: when the template is created and when the limit of data increases
//it subscribes again
Template.t_elementSubHeader.onCreated( function() {
Session.set('reqLimit',50);
var self = this;
//Everytime reqLimit changes I redo the subscribe
this.autorun(function(){
self.subscribe('generalMusics', Session.get('reqLimit'));
});
//CLIENT: more elements are sent to the template when reqLimit increases
Template.t_elementSubHeader.helpers({
data: function() {
return Musics.find({}, {limit : Session.get('reqLimit')});
}
});
//Also on client, when the user reach the bottom of the page
Session.set('reqLimit',Session.get('reqLimit')+50);
It works well but all the template elements are re-rendering and it also takes some time to do so. It's very inconvenient for the user, I think it takes time because I'm displaying pictures and not text (we already compress the pictures to a minimum size).
The problem is due to the subscribe that rerender all the template elements.
How can I do to just add the new elements and prevent the re-rendering of the already displayed elements when I subscribe ?
My app will be on mobile devices so I can't subscribe to a lot of elements and then just increase the limit in the template helper.
Finally I got it, i've added some code in the html to wait the subscription to be ready and I forgot about it.
I removed:
{{#if Template.subscriptionsReady}}
{{> Template.dynamic template="t_elementList" data=tabData}}
{{/if}}
Infinite scroll is working like a charm.

Is there an elegant way to refresh a given template with Iron Router?

Since my variables are not reactive and there are probably over 500 variables in my script, there is not feasable way I can make everything reactive right now.
So my question is, is there any way to make Iron Router refresh the current route/template when prompted? Right now, the only way I accomplish this is using document.location.reload(true);, but that is an ugly looking and very slow process.
Let's also say that I have a {{> yield}} element in my template: is there any way to just refresh that part without refreshing the entire page?
You probably need to define a reactive variable (Session or ReactiveVar) and change the state of that variable. On your template, make an if wrapping the part you need to refresh. When you change the state, the part inside the if will be refreshed.
helpers:
h_checkToRefresh: function() {
if (Session.get('count') > 0) return true;
else return false;
}
template
{{#if h_checkToRefresh}}
{{>yield}}
{{/if}}

Spacebars-generated dynamic links do not trigger Iron Router in Meteor?

I've got this in my routes:
Router.route('/videos/:id', {
name: 'VideoPage',
data: function(){
return Videos.findOne(this.params.id);
}
})
This template shows up at the route above:
Template.VideoPage.helpers({
'videoIds': function(){
var myVideoIds = [
"23456",
"h5e45t",
"f4e4w",
"g6h4h"
];
return myVideoIds;
}
});
HTML:
<template name="VideoPage">
{{videoTitle}}
<p>Click the links below to get to a new video page</p>
{{#each videoIds}}
<a href="/videos/" + {{this}}>
{{/each}}
</template>
When I click on a link, the URL in the browser changes from something like /videos/23456 to something like /videos/f4e4w, but the request never actually goes through Iron Router and the Router.route function. I put a debugger before Router.route and it triggers on initial page load but does NOT trigger when the links are clicked.
I understand that Iron Router's default behavior is NOT to re-render a template the user is currently on, but this is the same template with different url params that are used to change the data in the template, so IMO it should still re-render.
Ok, false alarm. It appears that Router.route DOES fire and updates the data context every time the params._id changes. I was placing the debugger outside of the Route function when I should have been placing it inside of the data context function.
The example that I gave in this answer was also a highy, highly simplified example. It wasn't working in my real-life project due to something else (a complex video iframe generator) that was being refreshed improperly.
But rest assured that going from /videos/f4e4w to /videos/23456 by clicking a link DOES still go through Iron Router and the params does get read and the data does get updated.

Resources