iron-router data function for single item page - meteor

Router.route('/product/:product_id', {
template: 'productmain',
//data: function() {
// //console.log(this.params.product_id);
// return this.params.product_id;
//}
data: function (){
_id = this.params.product_id;
product = Products.find({pid: _id});
templateData = {
_id: _id,
product: Products.find({pid: _id}),
title: product.title
};
return templateData;
}
})
title & product seem to be empty, any ideas?
I can't fathom why these two are not working in my template:
<div class="col-md-9 col-xs-9">
<h1>{{ title }}</h1>
</div>
<div class="col-md-9 col-xs-9">
<h1>{{ product.title }}</h1>
</div>
If I do a Products.find({pid: _id}) in a helper function it works fine but I need a different display for this one product, hope that make sense.

Just use product = Products.findOne({pid: _id}); in your data function. You're showing an individual product in a template, not a cursor.
You could simplify the whole thing as follows:
Router.route('/product/:product_id', {
template: 'productmain',
data: function (){
return Products.findOne({pid: this.params.product_id});
}
});
then in your html just do:
<div class="col-md-9 col-xs-9">
<h1>{{_id}}{{ title }}</h1>
</div>
Basically the data function returns a single object which becomes this for the template. All attributes of this are available without prefixing, i.e. {{this._id}} can be shortened to {{_id}}

Related

How to render WordPress rest api datawith vue.js

I'm doing project themming WordPress using vue.js and wp rest API. But now I can not render data. Here is my code
app.js
var App = Vue.extend({});
var postList = Vue.extend({
template:'#post-list-template',
data: function(){
return {
posts: ''
}
},
ready: function(){
posts = this.$resource('/wp-json/wp/v2/posts?per_page=20');
posts.get(function(posts){
this.$set('posts', posts);
})
}
})
var router = new VueRouter({
routes: [
{ path: '/', component: postList }
]
})
new Vue({
el: '#app',
router: router,
template: '<router-view></router-view>'
})
**index.php**
<?php get_header(); ?>
<div class="white-wrap">
<div id="app">
<router-view></router-view>
</div>
</div>
<template id="post-list-template">
<div class="container">
<div class="post-list">
<article v-for="post in posts" class="post">
<div class="post-content">
<h2>{{ post.title.rendered }}</h2>
</div>
</article>
</div>
</div>
</template>
<?php get_footer(); ?>
I don't know if I'm doing the right thing, because I am new in vue.js even any languages I'm just a beginner.
Within your data function your returning the posts as an empty string. It should be an empty array.
Right now your trying to use v-for to loop over a string of posts. You should be looping through an array of post objects.
Also, instead of the ready function use an earlier hook like beforeCreate
That should take care of your problem.

Meteor Blaze.renderWithData how to InsertAfter is it possible?

I'm having a problem to insert a template after and not before a node. For example:
//Html looks like this
<div class="questions">
<div class="question"></div>
<div class="question"></div>
<div class="question"></div>
</div>
<template name="question">
<div class="question"></div>
</div>
<template name="questionExtraInfo">
<div class="extra"></div>
</template>
I'm trying to get the following:
<div class="questions">
<div class="question"></div>
<div class="extra"></div>
<div class="question"></div>
<div class="question"></div>
</div>
Calling blaze render inside question event
Template.question.events({
'click .more-details': function () {
var instance = Template.instance();
Blaze.renderWithData(Template.questionExtraInfo, {}, document.querySelector('.questions'), instance.find('.question')));
});
I can only figure out how render it before or inside how about after?
<div class="extra"></div>
<div class="question"></div>
<div class="question"><div class="extra"></div></div>
I think a better approach would be to take advantage of reactivity:
Change your questions template to:
<template name="question">
<div class="question"></div>
{{# if shouldIncludeExtra }}
{{> questionExtraInfo }}
{{/if}}
</template>
The above template should be inside an each loop.
Then in your js something like:
Template.question.helpers({
'shouldIncludeExtra': function() {
// replace 'n' with the actual index. I think `this.index` is
// provided within #each blocks, or you can use the new `#each` helper.
var index = n;
return Session.get('shouldIncludeExtra' + index);
}
});
Then, in your click event, you set a session var based on the index to true:
Template.questions.events({
'click .question': function(e, tpl) {
var question = e.currentTarget;
// You can probably come up with something better here..
var index = $(question).parent().find('> .question').index(question);
Session.set('shouldIncludeExtra' + index, true);
}
});
Because of reactivity, you would see the inserts right away when you fire the click event.
I realize this doesn't really answer the headline of your question, but it should get you the desired outcome.

Template helper crashing app

My app is crashing my browser after implementing this columnWidth helper method. All I'm trying to do is rotate between col-md-7 and col-md-5 (Bootstrap classes) so that no two consecutive posts are the same width.
columnWidth: function() {
if (Session.get('columnWidth') === 'col-md-7') {
Session.set('columnWidth', 'col-md-5');
} else {
Session.set('columnWidth', 'col-md-7');
}
return Session.get('columnWidth');
}
The post template:
{{#each this}}
<div class="{{columnWidth}}">
<img src="{{image}}" height="350" width="{{imageWidth}}" alt="">
<div class="content">
<h2>{{title}}</h2>
<p>{{content}}</p>
<span class="dateAuthored">{{date}}</span>
</div>
</div>
{{/each}}
this refers to:
data: function() {
return Articles.find();
}
Any ideas why this is happening? I'm not receiving any errors. The browser tab just becomes unresponsive. Thanks.
You are constantly setting the same reactive variable so for example with the first div when the helper is called it will set it to col-md-7, then when it is called for the 2nd row you are changing the same variable to col-md-5 which is problematic for 2 reasons:
a) the template will redraw the first column and so they will both be col-md-5
b) the same helpers will get called again. I believe your browser crashes because you have created an infinite loop. Try console logging something inside your columnWidth helper and see how many times it gets called.
To achieve what you want you need to get the index of the {{#each }} loop and then have the column class dependent on whether it's odd or even. Unfortunately getting the index in meteor handlebars is a little tricky.
Try:
{{#each articles}}
<div class="{{columnWidth index}}">
<img src="{{image}}" height="350" width="{{imageWidth}}" alt="">
<div class="content">
<h2>{{title}}</h2>
<p>{{content}}</p>
<span class="dateAuthored">{{date}}</span>
</div>
</div>
{{/each}}
Then the following helpers:
articles: function() {
//'this' in this context should work.
//if not just replace with Articles.find().map(...
var articles = this.map(function(article, index) {
var i = _.extend(article, {index: index});
return i;
});
return articles;
},
columnWidth: function(index) {
if (index % 2 === 0)
return "col-md-5";
else
return "col-md-7"
}

Reactive-Tables Meteor

I am trying to get reactive-tables to work but I am having no luck following the instructions on GitHub.
This is what I have:
In my Main.html:
{{> courseTable }}
in my course_table.html:
<template name="courseTable">
<div id="table">
{{ > reactiveTable collection=Courses}}
</div>
</template>
in courses.js:(works with autoForm)
Courses = new Meteor.Collection("courses", {
schema: {....
Is there something I am missing? From my understanding once these commands are used, the rest is done from within the package. I can't find any more information on this package anywhere.
What I have now just shows a blank screen.
Thanks in advance!
This is what I have: (I'm using Meteor framework and bootstrap-3 package)
in index.html
<template name="clientes">
<div class="container">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Clientes</h3>
</div>
<div class="panel-body">
{{> reactiveTable collection=tables settings=tableSettings}}
</div>
</div>
</div>
</template>
in index.js
var Clientes = new Meteor.Collection('clientes')
Template.clientes.tables = function () {
return Clientes;
}
Template.clientes.tableSettings = function () {
return {
rowsPerPage: 10,
showFilter: false,
showNavigation: 'auto',
fields: [
{ key: 'nombre', label: 'Nombre' },
{ key: 'apellido', label: 'Apellido' },
{ key: 'correoe', label: 'E-mail' }
],
useFontAwesome: true,
group: 'client'
};
}
With this I can display all the records in the collection.
I hope this help you to go any further.
Courses is the collection object. To get some courses, you need to query the courses with find:
Courses.find()
However, to make this accessible in the template, you need a helper function.
//course_table.js
Template.courseTable.helpers({
courses: function () {
return Courses.find()
}
});
Then you can can set the table collection using the helper method (I used a lowercase "courses" for the helper method for clarity):
{{> reactiveTable collection=courses}}

Meteor data-context with iron-router

I am new to Meteor and I'm trying to set the data context in a page that displays one passage. I need to access the data in passage_item.js Template.passageItem.rendered but no context is set at that point. I think I need something like {{#with passage}} but "passage" does not exist in one_passage.html.
Here are some code snippets. Thanks.
router.js
Router.map(function() {
this.route('passagesList', {path: '/'});
this.route('onePassage', {
path: '/passages/:_id',
data: function() { return Passages.findOne(this.params._id); }
});
});
one_passage.html
<template name="onePassage">
{{> passageItem}}
</template>
passage-item.html
<template name="passageItem">
<div class="passage">
<div class="one-passage">
<h4>{{title}}</h4>
<div class="passage-content">
{{content}}
</div>
</div>
</div>
passage_item.js
Template.passageItem.helpers({
});
Template.passageItem.rendered = function() {
Meteor.defer(function() {
$('.passage-content').lettering('words');
//I want to be able to access the data object here. I have a list of words that are highlighted
});
};
Collection
Assuming you created your Passages collection like this and you've got autopublish turned on (which it is by default):
Passages = new Meteor.Collection('passages');
Router Map
And you mapped your router like this:
Router.map(function() {
this.route('onePassage', {
path: '/passages/:_id',
template: 'passageItem' // <-- to be explicit
data: function() {
return Passages.findOne(this.params._id);
}
});
});
Template
And your template looks like the template below:
<template name="passageItem">
<div class="passage">
<div class="one-passage">
<h4>{{title}}</h4>
<div class="passage-content">
{{content}}
</div>
</div>
</div>
</template>
The scope of 'this' in the template will be set to document returned by the Passages.findOne selector.
If the template doesn't render that means you're either searching for passage that doesn't exist, or your passage is missing title or content fields.
Rendered Function
Now for the last part of your question. The scope of 'this' in a rendered function is set to the template instance. So if you need to access the template data try this:
Template.passageItem.rendered = function() {
console.log(this.data); // you should see your passage object in the console
};
As of Meteor 1.0.3.1, the new Iron Router data selector appears to be...
Template.TemplateName.rendered = function() {
console.log(UI.getData());
};
I assume a passage consists of {'title':'', 'content':''}
Then this should work:
in router.js
Router.map(function() {
this.route('passagesList', {path: '/'});
this.route('onePassage', {
path: '/passages/:_id',
data: {
passage: function() { return Passages.findOne(this.params._id); }
}
});
});
in passage-item.html:
<template name="passageItem">
{{#each passage}}
<div class="passage">
<div class="one-passage">
<h4>{{title}}</h4>
<div class="passage-content">
{{content}}
</div>
</div>
</div>
{{/each}}
</template>

Resources