I want to add multiple Bootstrap Modals in one Yield.
Router.route('test', {
yieldTemplates: {
'contentTemplate': {to: 'content'},
'modal1Template': {to: 'modal'},
'modal2Template': {to: 'modal'}
}
});
This code adds only the last template to the yield -modal-. Is it possible to add multiple templates to one yield or do anybody know a best practice for this situation?
Related
I have a template rendering my Collection using {{#each Collection}}, I'm using iron-router to route this template like this:
Router.route('/home', function () {
this.render('home');
this.layout('header');
});
how can i use a "books" filter button so iron-router apply that filter to the subscription so i can only see the filtered version of my Collection like the following:
Collection.find({category: "books"});
There are a number of ways to approach this but one simple way would be to define a sub-route that takes a category as a parameter:
Router.route('/collections/:category',{
name: 'collections',
layoutTemplate: 'header',
data(){
return Collections.find({category: this.params.category});
}
});
Then your button code can just do Router.go('/collections/books') but you can now have multiple buttons each tied to different categories.
As suggested here https://guide.meteor.com/data-loading.html#organizing-subscriptions you can manage your subscription in Template and not in the route. So you can do:
import {ReactiveDict} from 'meteor/reactive-dict';
import {Template} from 'meteor/templating';
Template.home.onCreated(function(){
var that = this;
that.state = new ReactiveDict();
//that.state.set('selected-category',YOUR_DEFAULT_CATEGORY);
that.autorun(function(){
that.subscribe('subscription-name',that.state.get('selected-category'));
});
});
Template.home.events({
'click .js-category':function(e,tpl){
let category = tpl.$(e.currentTarget).data('category');
tpl.state.set('selected-category',category);
}
});
And in your Template:
<button type="button" data-category="books" class="js-category">Books</button>
Hope this will help you to find the right solution for your
I'm using the latest Meteor and Iron Router. Imagine have a 'customComputer' collection. Computers have three different states: 'ordering', 'building', 'shipped'.
Right now, I'm using three different routes for this, each with a different template
/o/_id
/b/_id
/s/_id
A computer can't be in 2 states at once, so I'd like to have one route. How do I wrangle the templates?
/c/_id
The best I can come up with is to make a "main" template that links to the others. Is this a best practice?
{{#if isOrder}}{{>orderTemplate}}{{/if}}
{{#if isBuilding}}{{>buildingTemplate}}{{/if}}
{{#if isShipped}}{{>shippedTemplate}}{{/if}}
Or dynamic templates
Here's the route:
Router.route('order', {
path: '/o/:b/:computerId',
onAfterAction: function() {
if (this.title) document.title = this.title;
},
data: function() {
if(!this.ready()) return;
var o = Computer.findOne(this.params.computerId);
if(!o) throw new Meteor.Error('Computer not found');
return o;
},
waitOn: function() {
if (!Meteor.userId()) return this.next(); // Don't subscribe if not logged in.
return [
Meteor.subscribe('computerById', this.params.computerId),
Meteor.subscribe('myProfile'),
];
},
});
Is there a better way?
I'd do your main template idea, or the dynamic template.
dynamic template tends to be better when you have quite a few options that can be dynamically configured.
But the main template I think ends up being more obvious when you only have a couple of choices.
Either way can be converted easily to the other if you think you need the other option.
Iron router allows to render different content into layout template, or load smaller templates into yields, but when user goes to different path, a content from previous yields does not unload templates inside them, until you force router to render null as a template into yields.
I have written a simple loop, which unload all yields before rendering new view, but i think there should be easier solution.
Router.route('/docs/container/', function () {
// render base layout for view
this.render('view');
// clear all parts
var yields = [
'viewSideLeft',
'viewSideRight',
'viewFooter',
'viewTopbar',
'pageContent',
'pageSideLeft',
'pageSideRight',
'pageFooter',
'pageTopbar'
];
for (var i = 0; i < yields.length; i++) {
this.render(null, {to: yields[i]});
}
// and render only this parts which you need:
this.render('viewDocsSideLeft', {to: 'viewSideLeft'});
this.render('viewDocsSideRight', {to: 'viewSideRight'});
this.render('viewDocsFooter', {to: 'viewFooter'});
this.render('viewDocsTopbar', {to: 'viewTopbar'});
this.render('pageDocsContainer', {to: 'pageContent'});
// this.render('pageDocsContainerSideLeft', {to: 'pageSideLeft'});
// this.render('pageDocsContainerSideRight', {to: 'pageSideRight'});
// this.render('pageDocsContainerFooter', {to: 'pageFooter'});
// this.render('pageDocsContainerTopbar', {to: 'pageTopbar'});
});
Here is a github issue related to this problem and it seems it has not been solved yet. https://github.com/iron-meteor/iron-router/issues/174
Most of the time, my search returns so fast that it's not worth flashing the loading template to the user...(in fact, it's distracting, as people are fine with a blank screen if the results are coming a split second later)...Is there any way to prevent the loading template from showing if the waitOn is only waiting for a short amount of time?
Here's my configuration
Router.route('/search', {
waitOn: function () {
return searchSubsManager.subscribe("search", Session.get('searchString'));
},
action: function () {
this.render('searchResults');
}
});
I saw that with this package:
https://github.com/Multiply/iron-router-progress
you can control whether it shows up for fast routes, but I don't need all that functionality, nor do I want the progress bar it provides... I'm just wondering if the basic iron router/ waitOn functionality can provide this ability.
There is not configuration to use on the waitOn function, but Why don't you create another layout template, and use it to show that fast routes?
<template name="noLoading">
{{> yield}}
</template>
Router.map(function () {
this.route('fastRoutes', {
path: '/someRoutes',
template: 'myHomeTemplate',
layoutTemplate: 'noLoading',
});
});
Update
or use the sacha:spin package and change the class name depending on the duration of the query.
if(queryDuration){
Meteor.Spinner.options = {
className: 'none'
}
}else{
Meteor.Spinner.options = {
className: 'spinner'
}
}
Every example that I have seen with iron-router specifies the template name with a string. Is it possible to do this with a variable? Suppose you have several routes that all use the same dynamic path, and the same data function, but they all need different templates. Is there a way to do this without specifying a different route for every template (which would also mean changing the path I use)?
You can programmatically specify things like the template and the layout with a custom action function. The example below demonstrates showing a particular template if the required document is found based on an id in the route. You can use the same semantics for both routes and controllers.
var postsController = RouteController.extend({
waitOn: function() {
return Meteor.subscribe('post', this.params._id);
},
action: function() {
if (Posts.findOne(this.params._id)) {
this.layout('postsLayout');
this.render('posts');
} else {
this.render('notFound');
}
}
});
Once 0.8.2 is released it should be trivial to do with UI.dynamic even without Iron-Router: https://github.com/meteor/meteor/issues/2123.