Ember query params not sending params in the request - ember.js

The query-params-new flag set to true.
Using latest ember and ember data. Ember: 1.6.0-beta.1+canary.b5b90241 ember.js and Ember Data : 1.0.0-beta.7+canary.b45e23ba
Application Adapter is set to this:
export default DS.RESTAdapter.extend({
host: 'http://example.com',
namespace: 'api/v2',
headers: {
"ClientId": "a-key",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "X-Requested-With"
}
});
The locations route looks like this:
export default Ember.Route.extend({
model: function(params){
return this.store.find('restaurant');
}
});
The locations controller looks like this
export default Ember.ArrayController.extend({
queryParams: ['lat', 'lon', 'limit'],
lat: null,
lon: null,
limit: null,
});
Navigating to this url http://example.com/locations?lat=47.620508&limit=22&lon=-122.349174 Ember data sends http://example.com/locations as the request.
I must be missing something?

There are a few things you need to do to get query-params-new working as expected.
First, you say you're using the latest ember, but don't specify whether it's the latest stable release or the latest canary release (master). In order to use query-params-new, you need to use canary, which is just the master branch. It is not available in the stable or beta releases yet, but you can download it here.
Second, you need to specify in your controller which params you want to bind to the route. Your locations controller would need to look something like this:
export default Ember.ArrayController.extend({
queryParams: ['lat', 'lon', 'limit']
});
All of this is documented on the Ember site. http://emberjs.com/guides/routing/query-params/
Edit based on additional question info:
It looks like you're not using the params in your route. You can use findQuery to send the params to the server like so:
export default Ember.Route.extend({
model: function(params){
return this.store.findQuery('restaurant', params);
}
});

Related

Routing error with ember-data 2.0 and emberjs 2.0.1

Cross-posting from discuss.ember. I am using Ember 2.0.1 with Ember-data 2.0 and default the default RESTSerializer generated by ember-cli. I know this question has been asked to many places before (which none have real answers) but no solutions have been working for me yet.
I have this model hook for a user model :
export default Ember.Route.extend({
model() {
return this.store.findAll('user');
}
});
Router is the following :
Router.map(function() {
this.route('users', { path: '/' }, function() {
this.route('user', { path: '/:user_id' }, function(){
this.route('conversations', { path: '/'}, function(){
this.route('conversation', { path: '/:conversation_id' });
});
});
});
});
For example, going to /conversations/4 transitions to users.user.conversations. My relations are defined in my models. In the user model I have a DS.hasMany('conversation') conversations attribute set with { embedded: 'always' }. Returned JSON looks like this :
{"conversations":[
{
"id":183,
"status":"opened",
"readStatus":"read",
"timeAgoElement":"2015-08-20T16:58:20.000-04:00",
"createdAt":"June 16th, 2015 20:00",
"user":
{
"id":4
}
}
]}
The problem I get is that Ember-data is able to add my data to the store but I get this error :
Passing classes to store methods has been removed. Please pass a dasherized string instead of undefined
I have read these posts : #272 and #261
Is it a problem with the JSON response?
Thank you. I have been using ember-data for quite a bit of time and never encountered this error before switching to ember 2.0.1 and ember-data 2.0.0
EDIT : I am now sure it is related to the embedded conversations because in ember inspector, if I try to see the conversations of a user (and the conversations are loaded into the store), it returns me a promiseArray which isn't resolved.
Try not to push objects to store directly. Possible use-case of .push() :
For example, imagine we want to preload some data into the store when
the application boots for the first time.
Otherwise createRecord and accessing attributes of parent model will load objects to the store automatically.
In your case UserController from backend should return JSON:
{"users" : [ {"id":1,"conversations":[183,184]} ]}
Ember route for conversation may look like:
export default Ember.Route.extend({
model: function(params) {
return this.store.find('conversation', params.conversation_id);
}
}
User model:
export default DS.Model.extend({
conversations: DS.hasMany('conversation', {async: true})
});
You don't have to always completely reload model or add child record to store. For example you can add new conversation to user model:
this.store.createRecord('conversation', {user: model})
.save()
.then(function(conversation) {
model.get('conversations').addObject(conversation);
});
P.S. Try to follow Ember conventions instead of fighting against framework. It will save you a lot of efforts and nervous.
Your conversation route has URL /:user_id/:conversation_id. If you want it to be /:user_id/conversations/:conversation_id, you should change this.route('conversations', { path: '/'}, function(){ to this.route('conversations', function(){ or this.route('conversations', { path: '/conversations'}, function(){

What array name does Ember Data expect for sub directory models?

I recently started learning Ember and using Ember-CLI so I'm not quite well educated about Ember Data and what array names it expects for relationships that are in sub directories in my app.
// models/server.js
import DS from 'ember-data';
export default DS.Model.extend({
serverHistory: DS.hasMany("history/server", { async: true })
});
// models/history/server.js
import DS from 'ember-data';
export default DS.Model.extend({
server: DS.belongsTo("server", { async: true })
});
I've tried returning these names from my API
server_historys_ids
server_histories_ids
history_server_ids
history_servers_ids
But I don't see an XHR request for Server history in my application. The servers itself are fetched fine.
Update
I changed my relationship name and the API is returning history ids but I'm still not getting an history json request even though I'm trying to each in the template. The game relationship data is accessible in the template and a request is successfully made.
// models/server.js
import DS from 'ember-data';
export default DS.Model.extend({
// attr's here.. not relevant
// Relationships
game: DS.belongsTo("game", { async: true }), // works
serverHistories: DS.hasMany("history/server", { async: true }) // doesn't make a request like game does.
});
I also have an adapter/history/server.js but it's only telling what namespace to use - "api".
Update 2
I think the problem may be in the way I'm calling the data to the model.
// routes/server/view/index.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
var parentModel = this.modelFor("server.view");
return this.store.query("server", { server_address: parentModel.server_address });
// return this.store.find("server", 1);
}
});
How come when I use find with an id it updates the template data and when I use query with parameters it doesn't?
Update 3
So I got my find and query problem sorted out, here's the way I got it to work: https://stackoverflow.com/a/31831667/1814027
The relationship problem still persists. I see no serverHistory data in my Ember toolbar nor a request being made to the API for it.
I beleive serverHistory is anti-conventional name for hasMany and serverHistories should be instead.
export default DS.Model.extend({
serverHistories: DS.hasMany("history/server", { async: true })
});
Then in case of ActiveModelAdapter expected server payload is:
{"server": {"id": 1, "server_history_ids": [1,2,3]}}
It doesn't depend on the fact that serverHistory is namespaced model, it depends on relation name only.
For example for model:
// models/server.js
import DS from 'ember-data';
export default DS.Model.extend({
bars: DS.hasMany("history/server", { async: true })
});
expected payload is:
{"server": {"id": 1, "bar_ids": [1,2,3]}}
Update
Working ember-cli example: https://github.com/artych/so_ember_data_subdir
Artych's answer helped me on the right path but Ember didn't want to recognise server_history_ids so I just renamed the hasMany relation to histories and returned histories: [] from my API. Now it works.. don't know why but it works.

Does ember-data subsequent find generates XHR every time without caching?

I have an app built using ember-cli 0.2.5 (which is Ember 1.12.0 and Ember-Data 1.0.0-beta.17).
My models' store.find() always generate XHR request to my backend. I would expect subsequent route accesses to use the store's cache.
I have two routes, router.js is:
Router.map(function() {
this.route('rules', {path: '/rules'});
this.route('users', {path: '/users'});
});
The routes models are:
Ember.Route.extend({
model: function (params) {
return this.store.find('user');
}
});
and
Ember.Route.extend({
model: function (params) {
return this.store.find('rule');
}
});
I am using the RESTAdapter and targeting an apache server which executes a perl cgi. The returned JSON (snippet) is:
{"rules":[{"canAutoUnblock":1,"creator":"spaling","status":null,"autoUnblockDate":"2015-05-30","createTime":"2015-01-19 19:59:56","privComment":"not private","pubComment":"Port scanning the Library","id":12,"ipaddr":"31.7.59.152"},{"canAutoUnblock":0,"creator":"spaling","status":"delete","autoUnblockDate":null,"createTime":"2015-01-19 19:59:56","privComment":"private","pubComment":"public","id":13,"ipaddr":"31.7.59.160"},
formatted ...
{
rules: [
{
canAutoUnblock: 1,
creator: "spaling",
status: null,
autoUnblockDate: "2015-05-30",
createTime: "2015-01-19 19:59:56",
privComment: "not private",
pubComment: "Port scanning the Library",
id: 12,
ipaddr: "31.7.59.152"
},
{
canAutoUnblock: 0,
creator: "spaling",
status: "delete",
autoUnblockDate: null,
createTime: "2015-01-19 19:59:56",
privComment: "private",
pubComment: "public",
id: 13,
ipaddr: "31.7.59.160"
},
Any advice greatly appreciated.
Barry
This is expected behavior for find with no additional parameters.
store.find('modelName')
This will ask the adapter's findAll method to find the records for the given type, and return a promise that will be resolved once the server returns the values. The promise will resolve into all records of this type present in the store, even if the server only returns a subset of them.
See http://emberjs.com/api/data/classes/DS.Store.html#method_find
If you want cached records only use
store.all('modelName')
http://emberjs.com/api/data/classes/DS.Store.html#method_all

How to access query parameters from route in Ember 1.7

In 1.7 Ember should support Query Parameters. I have no problems using them in controller but I'd like to access them in Route, ideally in beforeModel hook but model hook would work as well.
The API docs mention a queryParam parameter for the beforeModel hook but if I try to use it, it is always undefined.
The Query Parameters guide seems to suggest that the query parameters should be accessible as a part of the first parameter to the model hook. But that is also undefined. See the code below for examples.
Is there a way to access the query parameters from Route?
Thank you for your help.
App.ApplicationRoute = Em.Route.extend({
beforeModel: function(transition, queryParams){
console.log(queryParams.test); //undefined at /?test=123
},
model: function(params){
console.log(params.test); //undefined at /?test=123
}
});
Pretty sure it's a bug, but you can access them in the meantime via the transition object:
App.ApplicationRoute = Em.Route.extend({
beforeModel: function(transition){
console.log(transition.queryParams.test);
}
}
By specifying the query params in the controller, params will contain them automatically
ApplicationController = Ember.Controller.extend({
queryParams: ['test'],
test: null
});
In the latest version of ember (2.12 at the time of writing this answer), queryParams can be accessed in the model hook as follows:
import Ember from 'ember';
export default Ember.Route.extend({
queryParams: {
test: ''
},
model(params) {
console.log(params.test);
},
});
Observe that now both dynamic segment and queryParams are accessible via the params object. Since params is not available in the beforeModel hook, this solution works on when you have to access the queryParams in the model hook.
In latest ember version you can get the value in Route as
import Ember from 'ember';
export default Ember.Route.extend({
beforeModel(params){
console.log(params.queryParams.test); //if the parameter contains test as the key
}
});
This works only if the locationType is auto in your environment.js file.
If you want to access in didTransition action,
didTransition: (queryParams) ->
console.log(#get('queryParams'))

How to properly use Fixtures with ember-cli project structure

I'm using ember-cli and trying to make some sense of the structure of the app and how it is all wired together. There are some differences in the main Ember guide docs and what I'm seeing in the ember-cli generated project. I understand the API's are moving fast so I just need to be pointed in the right direction.
In router.js I have the following:
Router.map(function() {
this.route('domains', {path: "/domains" });
});
Then I have models/domain.js
import DS from 'ember-data';
var Domain = DS.Model.extend({
name: DS.attr('string')
});
Domain.reopenClass({
FIXTURES: [
{ id: 1, name: 'User'},
{ id: 2, name: 'Address'}
]
});
export default Domain;
And I have routes/domains.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.all('domain');
}
});
And finally ( I think ), I have templates/domains.hbs
<h1>Domains</h1>
{{#each}}
<p>{{name}}</p>
{{/each}}
Only the header is being rendered when I visit the http://localhost:4200/domains url. I'm using the ember chrome extension and I don't see any data coming back in the request. I'm not sure if it is a naming convention issue or what I'm doing wrong so any help is appreciated.
all just returns records that have already been found in the store. find will issue a request (in this case hitting the fixtures) and populate the store, and also return all of the records in the store.
this.store.find('domain');
The problem ended up being 2-fold. Kingpin2K was right in that I needed to use find instead of all. I also had to change the adapter to the following in adapters/application.js:
export default DS.FixtureAdapter.extend();