Meteor Pagination with alethes:pages - meteor

I'm using alethes:pagination but I don't understand how to make it work. I have 4 posts in my collection and I want to display 2 per page. Here's the code.
app.js
BlogPosts = new Mongo.Collection("blogPosts");
if (Meteor.isClient) {
Template.body.helpers({
blogPosts: function() {
return BlogPosts.find({});
}
});
}
Pages = new Meteor.Pagination(BlogPosts, {
itemTemplate: "post",
perPage: 2
});
app.html
<head>
<title>pagination</title>
</head>
<body>
{{> pages}}
{{> pagesNav}}
</body>
<template name="post">
{{title}}
</template>

You have to provide 2 templates name to the alethes backed collection.
One for the page itself, and another for the items of your paginated content.
In your JS
PaginatedStuff = new Meteor.Pagination(Polls, {
perPage:6,
templateName: 'paginatedStuff',
itemTemplate: 'stuffListItem'
});
Where you want to have your paginated content :
{{>paginatedStuff}}
And finally the two templates
<template name="paginatedStuff">
{{> pages}}
{{> pagesNav}}<!-- bottom navigation -->
</template>
<template name="stuffListItem">
<!-- stuff to display your item here -->
</template>

Related

Flow Router Footer Flashes to Top Before Data Loads

I'm loading a grid of data with flow router, but when I view the page the footer always flashes to the top before the data loads. What is the best way to fix this?
Here is the route:
AdminRoutes.route('/dashboard', {
name: 'adminDashboard',
action() {
BlazeLayout.render('AppLayout', {page: 'AdminDashboard'});
}
});
Here is the js file:
import { Template } from 'meteor/templating'
import Stores from '../../../../api/stores/stores.js'
import './AdminDashboard.html'
Template.AdminDashboard.onCreated(function() {
var self = this;
self.autorun(function() {
self.subscribe('stores.names.links');
});
});
Template.AdminDashboard.helpers({
stores: function () {
return Stores.find();
}
});
Here is the html layout file:
<template name='AppLayout'>
{{#if Template.subscriptionsReady}}
{{> Header }}
{{> Template.dynamic template=page}}
{{> Footer }}
{{/if}}
</template>
Here is the dashboard html file:
<template name='AdminDashboard'>
<div class='admin-dashboard-page'>
<section class='stores-grid'>
{{#each stores}}
<div class='store'>
<h2 class='store-name'>{{name}}</h2>
<a href='/admin/dashboard/{{link}}' class='store-button'>Edit</a>
</div>
{{/each}}
</section>
</div>
</template>
I'd try displaying the footer AFTER .stores-grid loads. Create a reactiveVar with a handler that is set to true when your data is loaded and return it's value on a helper, then wrap the footer in an if block on your template.
It would be something like the following...
First create a reactiveVar with a value of false:
Template.AdminDashboard.onCreated(function() {
this.isDataLoaded = new ReactiveVar(false);
var self = this;
self.autorun(function() {
self.subscribe('stores.names.links');
});
});
Set the value to true when the collection is loaded:
Template.AdminDashboard.helpers({
stores: function () {
let data = Stores.find()
if(data) {
Template.Instance().isDataLoaded.set(true)
}
return data ;
},
dataLoaded: function () {
return Template.Instance().isDataLoaded.get();
}
});
Finally, wrap your footer so it's only displayed after data is loaded:
<template name='AppLayout'>
{{#if Template.subscriptionsReady}}
{{> Header }}
{{> Template.dynamic template=page}}
{{#if dataLoaded}}
{{> Footer }}
{{/if}}
{{/if}}
</template>
A simple fix would be to set a minimum height on the div your content will be loaded into, pushing the footer down while the content loads. This may or may not work for you, depending on what the expected height of your content will be.
You could also install a loading screen/animation to hide the footer while the data loads.

Meteor blaze, Use helper / variable in Content Blocks (contentFor)

I have a template (navBarContent) that I is passed a "title" when I insert it.
I am then able to access {{title}} within that template, but it is not possible to access it within a {{#contentFor}} block embedded in the navBarContent template:
<template name="map">
{{>navBarContent title="MAP"}}
... other content ...
<template>
<template name="navBarContent ">
{{title}}
{{#contentFor "headerTitle"}}
<h1 class="title">{{title}}</h1>
{{/contentFor}}
</template>
I already tried to "forward" the title:
<template name="navBarContent ">
{{title}}
{{#contentFor "headerTitle" title="MAP"}}
<h1 class="title">{{title}}</h1>
{{/contentFor}}
</template>
which produces the following error:
First argument must be a function, to be called on the rest of the arguments;
EDIT:
Ok. I think the data scopes are a the following:
<template name="layout">
{{> yield "headerTitleRenderedInLayout"}}
{{> yield}}
</template>
<template name='map'>
{{> yield "headerTitleRenderedInTemplate"}}
{{>navBarContent title="PARAMETER_TITLE"}}
</template>
<template name="navBarContent">
{{title}} <!-- output: PARAMETER_TITLE -->
{{#contentFor "headerTitleRenderedInLayout"}}
<h1 class="title">{{title}}</h1> <!-- output: LAYOUT_DATA_TITLE -->
{{/contentFor}}
{{#contentFor "headerTitleRenderedInTemplate"}}
<h1 class="title">{{title}}</h1> <!-- output: TEMPLATE_DATA_TITLE -->
{{/contentFor}}
</template>
Above outputs are produced when I use the following router options:
Router.route('/map', function () {
this.layout("layout", {
data: function() {
return { title: "LAYOUT_DATA_TITLE" }
}
});
this.render('map', {
data: function() {
return { title: "TEMPLATE_DATA_TITLE" }
}
});
});
My app has a navbar that is defined in my main layout and I therefore need to set the datacontext for the layout in my route. So far so good, but I want to set that data context based on the value that I pass via:
{{>navBarContent title="PARAMETER_TITLE"}}
This is just a cosmetic thing, because I prefer to define my navbar content in the different templates rather than the routes.
It works when you pass the data context to the render function because Iron Router handles the contentFor block:
Router.route('/', function() {
this.render('map', {
data: function() {
return { title: 'MAP' }
}
});
});
Then the following template shows MAP twice:
<template name="map">
{{> navBarContent }}
{{> yield 'anotherBlock'}}
</template>
<template name="navBarContent">
<div>
In "map": {{title}}
</div>
{{#contentFor 'anotherBlock'}}
<div>
In contentFor: {{title}}
</div>
{{/contentFor}}
</template>

How to append Template Data to another Template based on Button Click in Meteor JS?

One template have button and another template have contains one text field.When ever button clicked that text filed append to the button template at the same time not remove the previous text fields that means the button clicked in 4 times 4 text fields add to the button template.
See the following code :
HTML Code :
<head>
<title>hello</title>
</head>
<body>
<h1>Welcome to Meteor!</h1>
{{> hello}}
</body>
<template name="hello">
Add Text Fields here :
<button>add another text box</button>
</template>
<template name="home">
<input type="text" id="name" />
</template>
JS Code :
if (Meteor.isClient) {
Template.hello.events({
'click button': function () {
//Here to write append logic
}
});
}
I didn't get any idea about this.So please suggest me what to do for this?
Use a client side only collection. Clicking adds a new record. Then in home template you loop on this. new Meteor.Collection(null) the null will tell it that it is local only and won't actually create the collection in the MongoDB.
if (Meteor.isClient) {
var buttonClicks = new Meteor.Collection(null),
clickCounter = 0;
Template.hello.events({
'click button': function () {
buttonClicks.insert({click: clickCounter++});
}
});
Template.home.helpers({
clicks: function () {
return buttonClicks.find({});
}
});
}
<template name="home">
{{#each clicks}}
<input type="text" id="name_{{click}}" />
{{/each}}
</template>

Meteor: insert template between other templates and transfer data between templates

I'm using Meteor for creating web application. I have defined my layout is:
<template name="default_layout">
{{> header}}
body code here
{{> footer}}
</template>
And here is my routing file:
Router.configure({ layoutTemplate: 'default_layout'
});
Router.map(function() { this.route('post_list', {path: '/'});
});
So. I have two questions:
How to make template post_list go into body code of default_layout template ?
Base on each layout for mapping page, maybe header and footer change content respectively. So, how to contact between template? For example, post_list template will set some value for header template ...
Thanks :)
Use the {{> yield}} helper. This will insert whatever template your route is serving. So.
<template name="default_layout">
{{> header}}
{{> yield}}
{{> footer}}
</template>
If you want to change what goes into the header, you will be using "yield regions.
<template name="default_layout">
{{> yield "header"}}
{{> yield
{{> yield "footer"}}
</template>
Then, in, say, a route controll you could do this:
PostController = RouteController.extend({
yieldRegions: {
'postHeader': {to: 'header'},
'postFooter': {to: 'footer'}
}
})
Then in your post_list route, do this:
Router.route('post_list', function(){
controller: 'postController'
});
Basically, you are creating a controller that can be re-used for certain routes, and telling the controller to put a template called "postHeader" into the {{> yield "header"}} region and "postFooter" into the {{> yield "footer"}} region.

How to render a dynamic layout and a static in the main content

I´m just starting with meteor coming from ember. What i have is a menu and the items get rendered into the maincontent layout. Now i would like to have a second menu in the maincontent layout.
Example: I click on people in the navigation and get a list of people. Now i click on a person and i get the details of that person. The navigation is still visible. This is what i have so working so far.
Now i would like to have another menu in the person template with items like todo, events.
Router.configure({
layoutTemplate: 'layout'
});
<template name="person">
//shows the details of that one person
</template>
<template name="events">
//shows the events of that one person
</template>
<template name="todos">
//shows the todos of that one person
</template>
<template name="personlayout">
persondetails
todos
events
</template>
The 3 links obove should always be visible as long a the person template is shown. Like when navigating to localhost:3000/person/5403789845ef834ed58ae745
So how can i render the person or todos or events template in the personlayout template?
First you need to define yield in personLayout.
<template name="personLayout">
{{yield}}
{{yield "persons"}}
{{yield "todos"}}
{{yield "events"}}
</template>
Now you can use this layout:
Using Routes
Router.route('/post/:_id', function () {
this.layout('personLayut');
// render the Post template into the "main" region
// {{> yield}}
this.render('Post');
// render the person template into the yield region named "person"
// {{> yield "persons"}}
this.render('person', {to: 'person'});
// render the todos template into the yield region named "todos"
// {{> yield "todos"}}
this.render('todos', {to: 'todos'});
});
Using contentFor
<template name="Page">
<p>
EVerything from here is going to `personLayout` {{> yield}}
</p>
{{> contentFor region="person" template="person"}}
{{> contentFor region="todos" template="todos"}}
{{> contentFor region="todos" template="events"}}
</template>
Read IronRouter docs

Resources