In the details page, I want to get the data from collection. When the code is like this, it works fine:
table
tr
td {{getLabel 'name'}}
td #{name}
tr
td {{getLabel 'qty'}}
td #{qty}
//- [...]
However, it is a long table, so I create a helper:
Template.jobDetails.helpers
# define what data to show
detailsList: ['name', 'qty'] # and many others
getLabel: (arg) ->
Schema.Job.label arg
getData: (arg, data) ->
# console.log data # it shows twice
# console.log data.qty # it shows twice (doesn't work)
data[arg] # doesn't work
table
//- detailsList is an array of field names
each detailsList
tr
//- `this` represent the field name (a string)
td {{getLabel this}}
//- `..` is the data object in the collection
td {{getData this ..}}
In the console.log data
, the browser console shows twice output for each detailsList
loop: One is an empty object, another correctly show the object of the data in collection.
Why does this problem occurs?
And, is there any Meteor way / packages to achieve this? (Pick some data field, and to show in order)
Many thanks in advance.
@edditoria you are using it differently to how I did it.
Manual says http://docs.meteor.com/api/templates.html#Template-helpers
Template.myTemplate.helpers({
displayName(firstName, lastName, keyword) {
var prefix = keyword.hash.title ? keyword.hash.title + " " : "";
return prefix + firstName + " " + lastName;
}
});
Is then called as so:
{{displayName "John" "Doe" title="President"}}
So in your example I believe console.log arg
would output the value of this
and arg.field
would be the reference to a property of this
Thanks for reply.
I understand this
is the string in the list detailsList
, so I passed ..
parameter which is the doc in collection to helper (If I am right). Each console.log shows the data
twice: One is empty and another correctly shows the object ( {name: 'Test Name', qty: 100}
). As a result, the web page shows the label in first column and empty field in second.
I aimed to work out a helper so it works dynamically when page content change (e.g. some data is not presented by a table), data change or anything I want to do. (Currently I’m making the “view” page “editable” if the viewer is owner, which case may use Autoform or not)
Um… thinking about your example, I cannot find a way to fit my need. Please help.
Ok , so first please show the contents of detailsList
so we can see what data you have there.
If there are two values in detailsList
then the getData
helper will be being called twice as the each
will iterate twice over the object.
To reference the data
arguments value, let’s first check what data you actually got in there. So you can do this with console log data
and put the result as a reply here please.
When you say ‘doesnt work’ do you mean the value is returning undefined?
The detailsList is in the helper:
Template.jobDetails.helpers
# define what data to show
detailsList: ['name', 'qty', 'note'] # 3 strings in arrar
getLabel: (arg) ->
Schema.Job.label arg # it works
getData: (arg, data) ->
console.log data # null x1 and then correct x1
data[arg] # throw error: Cannot read property...
The data in collection is simply:
# Jobs.findOne();
{
name: 'Test Name'
qty: '100'
note: 'Test note.'
}
Will it related to the code in Iron Router?
# show the Job Details page
Router.route '/job/id/:_id',
name: 'jobDetails'
data: -> Jobs.findOne { _id: @params._id }
Output in browser console:
null (job-details.coffee)
Exception in template helper: TypeError: Cannot read property 'title' of null (debug.js:41)
null (job-details.coffee)
Exception in template helper: TypeError: Cannot read property 'qty' of null (debug.js:41)
null (job-details.coffee)
Exception in template helper: TypeError: Cannot read property 'note' of null (debug.js:41)
Object {_id: "gMx3mXEoLkf4rMxgM", name: "Test Name", qty: 100, note: 'Test note.'} (job-details.coffee)
Object {_id: "gMx3mXEoLkf4rMxgM", name: "Test Name", qty: 100, note: 'Test note.'} (job-details.coffee)
Object {_id: "gMx3mXEoLkf4rMxgM", name: "Test Name", qty: 100, note: 'Test note.'} (job-details.coffee)
Hopefully there is a package to achieve this.
@edditoria: Yes it is related to iron router - I think this is due to the subscription not being ready at the first iteration.
In iron router setup the subscription in the waitOn
e.g this is working in my code
@route "invite-vendor",
path: "/invite-vendor/:_email"
waitOn: ->
[
subs.subscribe 'allpurchaseorders'
]
action: ->
#Check email exists
email = this.params._email
user = Meteor.users.find({emails: email}).fetch()
Please try in this manner