Ember defining model in route causing error - django

I'm pretty new to Ember, and I'm trying to set up a template that displays information about an external model (product). So I have an admin route:
App.AdminRoute = Ember.Route.extend({
model: function() {
var admin_brand = this.store.find('brand', 1);
return this.store.find('product', {brand: admin_brand});
}
});
controller:
App.AdminController = Ember.ArrayController.extend({
});
and template:
<script type="text/x-handlebars" data-template-name="admin">
<div class="row">
{{#each}}
{{name}}
{{/each}}
</div>
</script>
But I'm getting a JS error:
Error while processing route: admin undefined is not a function TypeError: undefined is not a function
I'm also using ember-data-django-rest-adapter for my actual data (which seems to be working fine otherwise). If I pass it a static array of objects in the route it works fine. Any ideas as to what I'm doing wrong? Also, is this even the correct way to go about this? Finally, is there a better way to debug these types of issues? I have the Chrome extension but it doesn't seem to help with these extremely generic errors, so any other tips on that would be awesome. Thanks very much for the help.

Assuming you are using ember data...
The issue is that the call to this.store.find('brand', 1) returns a promise, not a value. In order to use the value in the call to this.store.find('product', {brand: admin_brand}) you would need to use .then() to access the resolved value.
Something like this should work.
App.AdminRoute = Ember.Route.extend({
model: function() {
var self = this;
return self.store.find('brand', 1).then(function(admin_brand){
return self.store.find('product', {brand: admin_brand})
});
}
});

Related

Ember DjangoRESTAdapter data not loading

I'm pretty new to Ember so hopefully I'm just doing something stupid, but I've been running into a lot of random issues with data not displaying properly and I now see in the Ember Debugger that my data does not exist until I hit a specific model data endpoint. For instance, I have a template to display all products, here's the route:
App.ProductsRoute = Ember.Route.extend({
model: function() {
return this.store.find('product');
}
});
the controller:
App.ProductsController = Ember.ArrayController.extend({
itemController: 'product'
});
the template:
<script type="text/x-handlebars" data-template-name="products">
<div class="row">
{{#each}}
{{name}}
{{/each}}
</div>
</script>
Hitting the endpoint '/products' displays nothing initially, but if I go to '/products/1' I can see the product data in the view (and in the Ember debugger), and then if I navigate back to '/products' that particular product's data (but no other data) displays properly. So I'm super confused as to what I'm doing wrong. As the title suggests, I'm using the DjangoRESTAdapter if that helps narrow things down and here's my app.js as well
window.App = Ember.Application.create({});
window.api_location = 'http://localhost:8000/api';
App.ApplicationAdapter = DS.DjangoRESTAdapter.extend({
host: api_location,
pathForType: function(type) {
return Ember.String.underscore(type);
}
});
App.ApplicationSerializer = DS.DjangoRESTSerializer.extend({
});
App.Store = DS.Store.extend();
Thanks in advance for any help, and let me know if other code snippets would help.
Okay, I finally figured this out: it's an issue with pagination. I was not aware that we had pagination set up for our Django REST Api, so instead of returning a list of objects, it was returning a result object, with the list of products buried in a 'results' attribute. So until I can convince the other devs to turn off pagination I can modify all my queries:
this.store.find('product', {page_size:0});
to override our default page size.
Edit: I'm also trying out modifying the json response on the server side rather than using the djangorestadapter with this library: https://github.com/ngenworks/rest_framework_ember . Hopefully this saves some people some digging...

Ember route map url with query parameters

this is my route configuration (route.js using ember-cli)
this.resource('xero-invoices', {path:'/loans/xero/:loan_id/invoices'})
but ember cuts query string when trying to route this address . How to fix problem?
The portion of your route definition had a minor typo missing a closing curly brace, but I am assuming that is not really the issue. Here it is fixed for clarity.
this.resource('xero-invoices', {path:'/loans/xero/:loan_id/invoices'})
The resource above has a dynamic segment of lone_id not a query string. Query string support is currently in the beta builds of Ember and not in stable. Any query string functionality you are trying to use would be handled in your controller. http://emberjs.com/guides/routing/query-params/
If you had a jsbin or more code I may be more helpful.
Here is a trivial jsbin showing the dynamic segment working - http://emberjs.jsbin.com/casana/1/edit
Edit:
In your example jsbin you are trying to use the (query-parms) helper for link-to which is only available if you are using the beta version of Ember. In your application controller if you remove it from your application template you won't get an error. In your route, since you are returning the query param as the model, the oauth_token is accessible via the model property in the controller.
Source: http://jsbin.com/bufukiqisika/8/edit
App = Ember.Application.create();
App.Router.map(function() {
this.resource('xero-invoices', { path:'/loans/xero/:loan_id/invoices' });
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ["red","blue","green"];
}
});
App.XeroInvoicesRoute = Ember.Route.extend({
model: function(params) {
window.console.log(params);
return params.queryParams["oauth_token"];
}
});
Templates:
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="xero-invoices">
{{model}}
</script>
Example: http://jsbin.com/bufukiqisika/8#/loans/xero/09870987/invoices?oauth_token=foo
You can use query-parameters which are defined on controllers.
Something like this should work:
MyController = Ember.Controller.extend({
queryParams: ['searchvalue'],
searchvalue : null
})
And in you Template:
{{input type="text" valueBinding=controller.searchvalue}}
So your search value will be represented in the URL, e.g. “…/myapp/seach?searchvalue=foo”
See http://emberjs.com/guides/routing/query-params/

Creating a new record not pulling data from template fields

I am attempting to create a new record, however none of the data from the fields is being passed automatically, as I expected Ember to (from what I've read).
My template:
<form {{action save content on="submit"}}>
{{input value=name}}
<button type="submit"}}>Next</a>
From what I've read content is an alias for model and interchanging these makes no difference.
My route:
App.CampaignsNewRoute = Ember.Route.extend({
actions: {
save: function(campaign) {
console.log(campaign.name);
}
},
model: function(controller) {
return this.store.createRecord('campaign');
}
});
And my controller:
App.CampaignsNewController = Ember.ObjectController.extend({
pageTitle: 'New Campaign Setup'
});
When I hit 'Next' it logs undefined. Logging just the campaign shows it's an Ember model, but without the name attribute. name is defined on the campaign model. Setting the input to {{input value=content.name}} places the name attribute within the model returned, but it's still undefined. Am I missing anything in this process? The EmberJS site doesn't show how to do this, from what I can find.
--
As a side note: I was originally using App.CampaignsNewController = Ember.Controller.extend as my model was returning a hash of promises, one of which is an array and Ember didn't like me using either array or object controller. I simplified it to the above to verify it wasn't that which was causing the issue. So any solution taking this into account would be wonderful.
Edit: I can access the template fields by doing this.get('controller').get('name') but surely that is not necessary? Changing my controller to a Ember.Controller.extend also stops that from working, would love to know why. Clarification on best practice here would still be wonderful!
Edit2: this.get('controller.content').get('name') works if the controller is simply an Ember.Controller as opposed to Ember.ObjectController and the template has {{input value=content.name}}. I'll work with but hopefully someone can clarify this is the correct way.
ObjectController is the way to go here. You would have it backed by one particular model, your new model, and you would add additional properties to the controller for use in the template.
Code
App.IndexRoute = Ember.Route.extend({
actions: {
save: function(campaign) {
console.log(campaign.get('color'));
}
},
model: function() {
return Ember.RSVP.hash({
record: this.store.createRecord('color'),
all: this.store.find('color')
});
},
setupController: function(controller, model){
this._super(controller, model.record);
controller.set('allColors', model.all);
}
});
App.IndexController = Em.ObjectController.extend({
});
Template
In the template any time you want to access anything on the model backing the template, you can just access it as if the model is the current scope.
{{name}}
if you want to access any of the properties that exist on the controller you would use the property name that it is on the controller.
{{allColors.length}}
Here's an example:
<form {{action save model on="submit"}}>
Color:{{input value=color}}<br/>
<button type="submit">Next</button>
</form>
<ul>
{{#each item in allColors}}
{{#unless item.isNew}}
<li>{{item.color}}</li>
{{/unless}}
{{/each}}
</ul>
One last tip, always use getters and setters ;)
Ember Data hides the properties, they don't live right on the object, so campaign.name will return undefined forever and ever. If you do campaign.get('name') you'll get a real response.
With the example: http://emberjs.jsbin.com/OxIDiVU/792/edit

Ember.js ArrayController not Binding to correct controller?

I am experimenting around with integrating Ember.Data into my application and also wanted to find out how to propery use ArrayController. Unfortunately I didn't even get around simple databinding on the controller.
I simply can't figure out where I went wrong, so I fully expect someone to be able to point out: Hey you wrote .extend instead of .create
I am trying something rather similar to what Discouse is doing in their AdminSiteSettings:
The controller in question:
App.UsersController = Ember.ArrayController.extend({
foo: 'bar'
});
route:
App.UsersRoute = Ember.Route.extend({
model: function () {
var users = App.User.find();
return users;
},
setupController: function (controller, model) {
controller.set('model', model);
console.log(controller.get('foo')); // this works correctly => bar
}
});
Only problem: The template is being rendered, but I can't bind to the foo property:
<script type="text/x-handlebars" data-template=name="users">
We render the correct template
{{foo}}
</script>
Only problem is: The Template never renders 'bar'. It's just empty.
Now I found something similar in Discourse where they have a textbox bound to filter:
https://github.com/discourse/discourse/blob/master/app/assets/javascripts/admin/controllers/admin_site_settings_controller.js
I can't really understand why my controller property is not showing up, (and yes I am actually trying to get Ember.data to work, but since this can easily be reproduced without it I figured I'd settle for the simple foo: bar property :(
Versions in use:
Ember.js: v1.0.0-rc.4-23-gbfd3023
Handlebars: 1.0.0-rc.4
Ember.data: 13
Any pointers are welcome. Thanks!
I don't know exactly where you app fails, but I have tried to recreate your use case and in this example jsbin it's working correctly, have a look.
Hope it helps.

Correct way to connect a child view in ember.js pre4

I'm trying to figure out the correct way to connect a child view in Ember.js pre4.
I have the following html set as the template in the class App.ContactsShowView :
<div class="container">
<h1>Show Contact</h1>
ID:{{id}}
</div>
Info:
{{outlet infoarea}}
I would like render ContactsShowinfoView into the above outlet infoarea.
App.ContactsShowinfoView = Ember.View.extend({
templateName: 'contact/templates/contactsShowinfoView',
});
Reading the docs it would seem that this should be done via the renderTemplate method in the Route. I've tried multiple variations of the following code:
App.ContactsShowRoute = Ember.Route.extend({
renderTemplate:function() {
this._super();
this.render( "contactsshowinfo", {
outlet:"infoarea"
});
}
});
At best I get no error message and just get the ContactShow view displayed (But no, connect outlet).
Am I missing someting obvious?
You are not using consistent names for the view/template. Try this:
App.ContactsShowInfoView = Ember.View.extend({
templateName: 'contact/templates/contactsShowInfoView',
});
App.ContactsShowRoute = Ember.Route.extend({
renderTemplate:function() {
this._super();
this.render( "contactsShowInfo", {
outlet:"infoarea"
});
}
});