Problem of getting data of collection in helper

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