3

I am trying to add and push additional objects in my application. I have reproduced the case in this jsBin

To Achieve that I have followed this tutorial, which does exactly what I want.

I have a list of invoices and any invoice is composed by transactions. I can create a new invoice in my invoices create route where I want to add and push any single transaction.

  actions: {
    add: function() {
      var newTransaction = Ember.Object.create({
        name: "New Transaction",
        quantity: null,
        selectedFare: null,
        isDone: false
      });

      return this.get("content").pushObject(newTransaction);
    }

In my template this is how it looks

<tr>
{{#each controller}}
  <td>{{name}} {{input type=checkbox value=isDone checked=isDone}} {{input valueBinding=quantity}} {{view Em.Select prompt="test" contentBinding="controllers.fare.content" optionLabelPath="content.name" optionValuePath="content.id" selectionBinding="controllers.fare.selectedFare" }}</td>
{{/each}}
</tr>

Unfortunately I can not really see the error in the console. I don't know what is going wrong.

If from the template you remove{{#each controller}}{{/each}}, you can see one single transaction.

What's wrong in my code?

www139
  • 4,960
  • 3
  • 31
  • 56
Koala7
  • 1,340
  • 7
  • 41
  • 83

3 Answers3

2

Embers #each helper switches the current scope like so:

// this context is the controller
{{#each controller}}
 <td>{{name}}<td/> // this context is each transaction
{{/each}}

So whenever you try to access controllers you try to accesses it on your transaction object, where it doesn't exist. The reason why this worked in the tutorial you were following is that the guy there didn't try to access a controller property. No worries, this is confusing a lot of people and will therefore be deprecated in future ember versions.

To solve your problem, just use

// this context is the controller
{{#each transaction in controller}}
 <td>{{transaction.name}}<td/> // this context is still the controller
{{/each}}

or in your particular use case:

<tr>
{{#each transaction in controller}}
  <td>{{transaction.name}} {{input type=checkbox value=transaction.isDone checked=transaction.isDone}} {{input valueBinding=transaction.quantity}} {{view Em.Select prompt="test" contentBinding="controllers.fare.content" optionLabelPath="content.name" optionValuePath="content.id" selectionBinding="controllers.fare.selectedFare" }}</td>
{{/each}}
</tr>
Lazybensch
  • 506
  • 2
  • 5
  • Very frustrating and confusing, i have made the changes you said and i get this error in the console "Error while processing route: invoices.create" – Koala7 Dec 18 '14 at 12:53
  • This is most likely due to a typo in your template, can you post the content of your .hbs here? – Lazybensch Dec 18 '14 at 12:54
  • 1
    Ok so in your `add` action you are pushing your new transaction to the controllers content which made me think its an array controller of transactions. Now I see that the controller is holding a single `invoice` model that holds the transactions in its `transactions` property. So you would need to do `this.get("content.transactions").pushObject(newTransaction);`. To fix the error you also have to loop through the transactions like so: `{{#each transaction in controller.transactions}}` otherwise you would try to loop through a single invoice object – Lazybensch Dec 18 '14 at 13:08
  • I have tried again here but i can't, http://jsbin.com/saqira/12/edit?html,js,console,output, if you edit my jsbin then showing me better i accept your answer – Koala7 Dec 18 '14 at 17:08
2

I made some changes, but it needs improvement, feel free to ask further questions to improve it. Also see the emberjs guides todo example. Probably the tutorial is outdated see Ember store.push with hasMany doesn't update template?.

I refactored your add method like this:

add: function() {

  var transactionRecord = this.store.createRecord('transaction', {
    name: 'new transaction'
  });

  return this.get("model.transactions").addObject(transactionRecord);
}

The template to loop transactions is like this:

{{#each model.transactions}}

Finally I added invoices/index template so you can see the invoices and their transactions, when you click an invoice:

<script type="text/x-handlebars" data-template-name="invoice/index">
  <p> Invoice Index Route</p>
  <p> {{title}} </p>
  <p> Transactions: </p>
    {{#each transactions}}
      <ul>
        <li> name: {{name}} </li>
        <li> quantity: {{quantity}} </li>
      </ul>
    {{/each}}
</script>

The example: http://jsbin.com/gugukewaka/1/edit

Community
  • 1
  • 1
user3995789
  • 3,452
  • 1
  • 19
  • 35
  • Thanks, you put me in the right direction and answer is obviously accepted, just last question, in the new transaction record created there is now an input type checkbox which i have setup false as default (isChecked: false), in my InoiveCreateController, why although that, it s still displayed as checked? http://jsbin.com/vunime/1/edit?html,js,output – Koala7 Dec 21 '14 at 18:04
  • 1
    remove the quotes, [see input helpers](http://emberjs.com/guides/templates/input-helpers/#toc_checkboxes). @Koala7 – user3995789 Dec 21 '14 at 18:11
  • thanks,if you can also tell what 's the best way to insert the option values in my select it would be very appreciate in order to let the calculations working again – Koala7 Dec 21 '14 at 19:30
  • I suggest read ember guides all the way through, http://emberjs.com/api/classes/Ember.Select.html @Koala7 – user3995789 Dec 21 '14 at 19:33
  • thanks!, that was the way i built them up originally – Koala7 Dec 21 '14 at 19:42
1

In your invoices/edit template you are using

{{#each controller}}

but your InvoicesCreateController is ObjectController which is causing the issue. Either don't use #each in template because I am not getting why it is required or if it is really needed then change the InvoicesCreateController to ArrayController.

guleria
  • 741
  • 2
  • 11
  • 23
  • @Koala7 also when I see the code in chrome error is logged as `Uncaught Error: Assertion Failed: The value that #each loops over must be an Array. You passed App.InvoicesCreateController, but it should have been an ArrayController` when you try to go to edit route. – guleria Dec 24 '14 at 07:17