I'm using an unless spacebar function to check if a user has verified their email address. In production, I assume due to a delay, the screen displays this notice and then changes after a second if the email has been verified. Is there a way to slow down the page load so the users email status is checked before the page loads?
<template name="mainLayout">
{{#unless currentUser.emails.[0].verified}}
<p class="alert alert-warning text-center">We have sent you an email to verify your email address. All users must confirm their email address to access the BHR platform.</p>
{{else}}
<div id="content" class="content">
<div class="container">
{{>Template.dynamic template=main}}
</div>
</div>
{{/unless}}
</div>
</template>
The delay come because the first time the template is rendered the Meteor.user() object has not yet been fully loaded. Then it loads and reactively the sections get swapped.
You need to show a loading screen/spinner while the user object is loading. How you do this will depend on what router you are using.
I believe this is what Michael was suggesting. Wrap you templates in:
{{#if Template.subscriptionsReady}}
{{/if}}
Related
I'm not sure if this is a Meteor issue or a generic one but I have the following code in my app.
<template name='admin'>
<div class='admin container-fluid noPadding'>
{{#if isInRole 'Admin'}}
<h3 class="homepageText">Server Statistics</h3>
{{> serverFacts}}
{{else}}
You don't belong here!
{{/if}}
</div>
When the page renders I see "You don't belong here!", then "Server Statistics" replaces it a second or so later. I have the same problem other places in my app always with a Blaze {{#if ...}} involved. Is there a way to stop the page from displaying in the browser until the rendering has completed and settled down?
This is a generic issue with reactive applications - rendering often happens while the data is still being pushed to the client. The normal solution is to use a spinner (ex: sacha:spin) until the underlying subscription(s) are ready. Then in Blaze you end up with:
<template name='admin'>
{{#if loading}}
{{> spin}}
{{else}}
<div class='admin container-fluid noPadding'>
{{#if isInRole 'Admin'}}
<h3 class="homepageText">Server Statistics</h3>
{{> serverFacts}}
{{else}}
You don't belong here!
{{/if}}
{{/if}}
</div>
You'll need a helper to compute loading based on your subscriptions. In a more complicated layout backed by several subscriptions you might end up with more than one spinner spinning at a time.
I'm trying to create a quiz app on Meteor and have had trouble setting up Iron Router forever. I'll try to give a visual:
This is the front page:
Image 1
When a user clicks on the button shown above, I want the first question to show up, whose contents are filled from MongoDB.
Image 2
This is what my router looks like ("question" is the name of the question template, as seen in image 2):
Router.route("/quiz/:_id", {
name: "question",
data: function(){
return Quiz.findOne(this.params._id);}
});
Now, in order for me to get from image 1 to image 2, I have to use a mongo object _id in the html file.
<template name="main">
<div class="jumbotron">
<h2>
Welcome to Simple Meteor Quiz app!
</h2>
<p>
To try it out, simply click "start" below!
</p>
<p>
<a class="btn btn-primary btn-large" href="/quiz/cieLkdzvGZPwrnZYE">Start</a>
</p>
</div>
</template>
When I click "Next Question" on image 2 to go onto the 2nd question, it doesn't work. I don't know how to make this process dynamic.
The way it looks to me right now is that I physically have to create a new route for every single question, which would look really ugly really quickly.
Any way to help implement Iron Router in this scenario? I read Discover Meteor and thought I fully understood how Iron Router works, but the more I try to fix this, the more I get confused.
Edit:
To solve my dilemma, I simple created a helper function which I could place behind the /quiz/ in the main template to lead me to the quiz question, based on a suggestion by Michel Floyd.
So the helper ends up looking like this:
Template.main.helpers({
nextQuestion: function(){
queue = Quiz.find().fetch();
return queue[0]._id;
}
});
Then attached to the URL like this:
<a class="btn btn-primary btn-large" href="/quiz/{{nextQuestion}}">Start</a>
Basically just spit out the first _id of first item in the array by making the collection an array via find().fetch(). Will probably randomize the _id at a later time.
You need a way for each template to know what the next question is. For example you can add a nextQuestionId key to your Quiz object. Then your template can be:
<template name="main">
<div class="jumbotron">
<h2>
Welcome to Simple Meteor Quiz app!
</h2>
<p>
To try it out, simply click "start" below!
</p>
<p>
<a class="btn btn-primary btn-large" href="/quiz/{{nextQuestionId}}">
Start
</a>
</p>
</div>
</template>
I am using iron-router, i have a route "models" which has a list of items. When the user clicks one of these items a new route "model" is used, the name of the selected item is passed as a param and used to load data about that model from the database.
I want to use slick carousel, using an array of images returned from the database (based on the param).
<div id="carousel">
{{#each images}}
<div class="item">
<img src="/images/{{this}}" alt="">
</div>
{{/each}}
</div>
Where should I call the slick init?
Generally speaking, you should initialize plugins in a template's onRendered callback. In your case, that won't work because onRendered will fire before any of the images are inserted into the DOM. With other carousel plugins I've seen, the following strategy works:
Move each item to its own template (carouselItem).
Add an onRendered callback to carouselItem so that the plugin will be initialized after each item is added to the DOM.
I haven't tried this with slick carousel, but it would look something like this:
<template name="carousel">
<div id="carousel">
{{#each images}}
{{> carouselItem}}
{{/each}}
</div>
</template>
<template name="carouselItem">
<div class="item">
<img src="/images/{{this}}">
</div>
</template>
Template.carouselItem.onRendered(function() {
$('#carousel').slick();
});
Assuming slick carousel can be initialized multiple times, this approach should work. Be aware that one possible downside is that the plugin will refresh whenever images is updated. One way to fix that is to use the {reactive: false} option in your find.
Usually you would call a plugin on an element in Template.myTemplate.onRendered:
Template.xxx.onRendered(function() {
$('#carousel').slick();
});`
I'm migrating some code to blaze and have hit a problem with the bootstrap carousel that I can't seem to get over.
I had the following pre blaze to set one of the carousel items active to kick the whole thing off
<div class="item {{#if active_sponsor}}active{{/if}}">
As documented, this no longer works with blaze, so I've tried modifying it to the only thing I can think of which is
{{#if active_sponsor}}
<div class="item {{#if active_sponsor}}active{{/if}}">
{{else}}
<div class="item">
{{/if}}
This all lives within an {{each sponsors}} block.
Sadly, this fails to run with an error saying unexpected {{else}} (or, if I remove the {{else}} unexpected {{/if}}
What's the correct way to do this. I'm using exactly the same pattern earlier to change a
From "Using Blaze" on github :
https://github.com/meteor/meteor/wiki/Using-Blaze#conditional-attributes-with-no-value-eg-checked-selected
So you should use this form instead, assuming that active_sponsor is the property to look for in the current data context.
Template.whatever.helpers({
isActive:function(){
return this.active_sponsor?"active":"";
}
});
<div class="item {{isActive}}">
</div>
I want to render each article in my meteor Articles collection.
(File located in myProject/collections/collections.js so it should be available for both client and server)
Code in collections.js:
Articles = new Meteor.Collection('articles');
I've got the autopublish package installed and and i have inserted an object in the Article collection via the Chrome console and verified the insert via the console with: Articles.findOne()
Articles.insert({name: 'HTML5', description: 'HTML5 for beginners', src: 'https://www.youtube.com/watch?v=9gTw2EDkaDQ'})
What i have got so far is:
<head>
<title>Articles</title>
</head>
<body>
{{> main}}
</body>
My main template is the one that won't show the articles.
<template name="main">
<div class="container-fluid">
{{#each articles}}
{{> article}}
{{/each}}
</div>
</template>
And my article template which should be rendered for each of the objects in my Articles collection, looks like this:
<template name="article">
<div class="item well span4">
<iframe height="{{height}}" src="{{src}}"></iframe>
<hr>
<h4 class="muted">{{name}}</h4>
<p>{{description}}</p>
</div>
</template>
What do i need to add to render this article? And what would i have to do to render the article if i were remove the autopublish package?
What do i need to add to render this article?
You need to tell what your main template how to calculate the field articles. You simply do that by calling the helpers method on the template.
And what would i have to do to render the article if i were remove the
autopublish package?
You would need to create a publish, so the clients can get the documents in the collection by subscribing to it.