I'm trying to implement this route:
#route "buildingSpaceTenant",
path: "/buildings/:_building_id/spaces/:_space_id/tenants/:_id/communications"
template: "tenant"
yieldTemplates: {
Session.get("current_tenant_subtemplate"): {to: "subTemplate"}
}
but apparently I can't use the session object this way.
<runJavaScript-30>:148:11: client/routes/tenantsRoute.coffee:44: unexpected . (compiling client/routes/tenantsRoute.coffee) (at handler)
What's the right way?
You can't use variable names as keys in an object literal. If yieldTemplates can accept a function (I don't think it can), you could try something like:
#route 'buildingSpaceTenant',
path: '/buildings/:_building_id/spaces/:_space_id/tenants/:_id/communications'
template: 'tenant'
yieldTemplates: ->
templateName = Session.get 'current_tenant_subtemplate'
obj = {}
obj[templateName] = to: 'subTemplate'
obj
I had a look at the example from this issue which implies that you could try overriding action to achieve the same end result.
#route 'buildingSpaceTenant',
path: '/buildings/:_building_id/spaces/:_space_id/tenants/:_id/communications'
template: 'tenant'
action: ->
if #ready()
#render()
templateName = Session.get 'current_tenant_subtemplate'
#render templateName, to: 'subTemplate'
else
#render 'loading'
Give those ideas a try and let me know how it goes.
Related
Hi I have this route
#CoffeeScript
Router.route 'tests/:slug/:type/question/add',
name: 'addQuestion'
controller: testsAddQuestionController
And I have this controller
#testsAddQuestionController = testsQuestionsController.extend
template: 'mcqQuestionForm'
data: ->
questions: TestQuestions.find()
test: Tests.findOne slug: this.params.slug
And I want to select template from controller depending the value of :type parammeter, I tried two ways:
#testsAddQuestionController = testsQuestionsController.extend
template: if this.params.type is 'mcq' then 'mcqQuestionForm' else 'somethingelse'
data: ->
questions: TestQuestions.find()
test: Tests.findOne slug: this.params.slug
But with this approach I get the error this.params is undefined
Second approach
#testsAddQuestionController = testsQuestionsController.extend
template: if Router.current().route.params.type is 'mcq' then 'mcqQuestionForm' else 'somethingelse'
data: ->
questions: TestQuestions.find()
test: Tests.findOne slug: this.params.slug
But the applciation crashes with this approach, does any body know how to access to route parameters in order to make this conditionals for select template from controller?
Here is how our controller looks like:
#testsAddQuestionController = testsQuestionsController.extend
template: ->
qType = Router.current().params.type
if qType == 'practical'
'practicalQuestionForm'
else if qType == 'mcq'
'mcqQuestionForm'
data: ->
questions: TestQuestions.find()
test: Tests.findOne slug: this.params.slug
For some reason (no idea why) if I save the current Router param into a variable and then use the variable for the if statement then it works.
Hope this helps you.
In the next phase of my Meteor journey (read: learning the ropes!), I'd like to implement a simple search based on user inputed values, then redirect to a route specific to the record returned from the server.
At the moment, I'm picking up the inputed values via this code:
Template.home.events 'submit form': (event, template) ->
event.preventDefault()
console.log 'form submitted!'
countryFirst = event.target.firstCountrySearch.value
countrySecond = event.target.secondCountrySearch.value
Session.set 'countryPairSearchInputs', [countryFirst, countrySecond]
countryPairSearchInputs = Session.get 'countryPairSearchInputs'
console.log(countryPairSearchInputs)
return Router.go('explore')
Happily, the console log returns the desired countryPairSearchInputs variable - an array of two ids. In my routes.coffee file I then have the following:
#route "explore",
path: "/explore/:_id"
waitOn: ->
Meteor.subscribe 'countryPairsSearch'
On the server side, I have:
Meteor.publish 'countryPairsSearch', getCountryPairsSearch
And finally, I have a search.coffee file in my /lib directory that defines the getCountryPairsSearch function:
#getCountryPairsSearch = ->
CountryPairs.findOne $and: [
{ country_a_id: $in: Session.get('countryPairSearchInputs') }
{ country_b_id: $in: Session.get('countryPairSearchInputs') }
]
With regards to the search function itself, I have a CountryPairs collection where each record has two ids (country_a_id and country_b_id) - the aim here is to allow users to input two countries, with the corresponding CountryPair then being returning.
I'm currently struggling to tie all the pieces together - the console output on searching is currently:
Uncaught Error: Missing required parameters on path "/explore/:_id". The missing params are: ["_id"]. The params object passed in was: undefined.
Any help would be greatly appreciated - as you can probably tell I'm new to Meteor and am still getting used to the pub/sub methodology!
Edited: mixed up client/server for the publish method when I first posted - the danger of late-night posting!
First, seems you're expecting an :id parameter on your 'explore' route.
If I understand you're case, you're not expecting any params here, so you can just delete ':id' from your route:
#route "explore",
path: "/explore/"
waitOn: ->
Meteor.subscribe 'countryPairsSearch'
or either add a params to your Router.go call:
Router.go('explore', {_id: yourIdVar});
Secondly, you're trying to use a client function: Session.get() server-side. Try to update the publication using a parameter ; or using a method.call.
client-side
Meteor.subscribe 'countryPairsSearch' countryA countryB
not sure about the coffeescript syntax, check http://docs.meteor.com/#/full/meteor_subscribe
and server-side
#getCountryPairsSearch = (countryA, countryB) ->
CountryPairs.findOne $and: [
{ country_a_id: $in: countryA }
{ country_b_id: $in: countryB }
]
Router.map ->
#route '/foo'
Template.foo.events
'click something': ->
Router.current().params #is empty array
Router.go '/foo', thenGoTo: 'bar'
I want to access the thenGoTo: 'bar' object.
I could do Router.go 'foo', {} {query: 'thenGoTo=bar'} and then parse Router.current().url, but I'd rather keep a clean URL.
Why is it that .findOne() does not work when executed inside the Router?
It always returns undefined.
Yet .find() works without any problems. Also tested .findOne() by manually entering the condition and the ._id manually.
Is .findOne() not designed to work inside the Router?
It's working properly in my application. I implemented it like this:
Router.map(function() {
this.route('training', {
path: '/training/:id',
data: function() {
return Trainings.findOne({id: this.params.id});
},
notFoundTemplate: 'notFound',
title: "Training"
});
});
it works fine!
maybe you're trying to pass the result to an iterator? it's not a cursor.
try a find().fetch() and use the result in the same way.
if it's a data/timing issue you could also guard with a ready() function.
you don't need to if you're using it reactively but this gives you a bit more explicit knowhow when things happen, yet without using a waitOn.
in coffeescript:
#---------routes ---------
#route 'routeName',
path: '/path/to/:cname'
onBeforeAction: ->
Meteor.subscribe('Things', {
cname: #params.cname
})
this.next()
data: ->
if #ready()
data = {
params: #params
}
data.lesson = Things.findOne({cname: #params.cname})
return data
I have a simple subscription running in Iron Router.
#route 'AdminEditor',
path: '/admin/editor/:id?'
controller: 'AdminController'
template: 'AdminRoot'
yieldTemplates:
'AdminEditor': { to: 'adminAside' }
waitOn: ->
return Meteor.subscribe 'getArticle', #params.id
The publication:
Meteor.publish 'getArticle', (id) ->
return Articles.find { 'id': id }
My database is not empty and have a single document into it:
db.articles.find().pretty()
{
"authors" : [
"dqbxgrxzehXXTbFgG"
],
"date" : ISODate("2014-10-01T20:07:48.846Z"),
"title" : "Meteor #5",
"content" : "hello",
"id" : 1,
"_id" : "WL7ygMw2jL9WnmRYZ"
}
But when I go to /admin/editor/1 and type in my chrome debugger Articles.findOne(), it doesn't return anything. I also have defined the collection in a lib folder:
#Articles = new Meteor.Collection 'articles' # run on both client and server
I know there is probably a little thing I forgot, but the subscription seems to work: when I subscribe to it from the chrome debugger and do a find, it returns the object.
Meteor.subscribe('getArticle', 1);
Articles.findOne();
Can you log the value of #params.id in the waitOn to check what you're actually sending? It could be the fact that you're sending it as a string rather than an integer (as you are in the console). If so, you just need to parseInt and it should work.