I have merged together from this two problem (How to pass model in Nested routes - emberjs and Embedded data from RestApi) a JsBin example: http://jsbin.com/OxIDiVU/544
It works fine if you navigate customers-> info -> contact, but it will break if one calls directly a customer's contact eg.:http://jsbin.com/OxIDiVU/544#/customers/3/contact
Error while loading route: customer.contact Cannot set property 'store' of undefined TypeError: Cannot set property 'store' of undefined
When you do a request for a single record, it uses a different serializer endpoint and expects the data in a different format. The format it expects is:
{
customer: {
id: 1,
currency:1
},
currencies: [
{
id:1,
prop: 'foo'
}
]
}
And the endpoint in the serializer is extractSingle. Feel free to extract out the portions of extractArray that are similar and share those.
Pretending your payload is:
{
customer:{
id:3,
name:"Joue",
currency:{
id:5,
iso_code:"BDT"
}
}
}
Your extractSingle would be
extractSingle: function(store, type, payload, id) {
var customer = payload.customer,
currencies = [];
var currency = customer.currency;
delete customer.currency;
if(currency){
currencies.push(currency);
customer.currency = currency.id;
}
payload = { customer:customer, currencies: currencies };
return this._super(store, type, payload, id);
}
Here's the example, with a response for customer 3
http://jsbin.com/OxIDiVU/545#/customers/3/contact
your property name should match inside the model, and the root name (currencies here) should be the plural version of the type of record it is.
{
customer: {
id: 1,
default_currency:1
},
currencies: [
{
id:1,
prop: 'foo'
}
]
}
Related
I'm struggling to correctly type the endpointMeta object in my project.
It contains computed object keys that are related to 2 objects
services - contains the names of the services currently known. The number of services may increase later.
endpoints - define the endpoints available in the service, that are being called in the project.
enum services {
serviceNameOne = 'service1',
serviceNameTwo = 'service2',
serviceNameThree = 'service3',
};
const endpoints = {
[services.serviceNameOne]: {
getUser: '/getUser',
verifyDetails: '/s/verifyDetails',
},
[services.serviceNameTwo]: {
fetchCustomersv1: '/v1/fetchCustomers',
fetchCustomersv2: '/v2/fetchCustomersv1',
},
[services.serviceNameThree]: {
getAllProjects: '/g/a/p',
getProject: '/g/p',
updateProject: '/u/p',
}
}
endpointMeta - object contains some meta info about these endpoints
const endpointMeta = {
[services.serviceNameOne]:{
[endpoints.serviceOne.getUser]: {
description: 'something about getUser',
version: 1
},
[endpoints.serviceOne.verifyDetails]:{
description: 'something about verifyDetails',
version: 3
},
},
[services.serviceNameTwo]:{
[endpoints.serviceTwo.fetchCustomersv1]: {
description: 'something about fetchCustomersv1',
version: 1
},
[endpoints.serviceTwo.fetchCustomersv1]:{ // duplicate object :(
description: 'something about fetchCustomersv1',
version: 1
},
}
}
Edit
What I ideally want is for when other devs are introducing new services or endpoints, they should be forced to add an entry to the endpointmeta object.
TS Playground
I have a model company and a model address. company.address belongs to address. So when I fetch a company record model(params) {return this.store.findRecord('company', params.companyID);}I can access the address attributes with model.address.street. But when my backend retruns address: null because the company dosnt have a relationship with an address and I want that the user can set the street by a input field, I get the error Assertion Failed: Cannot delegate set('street', a) to the 'content' property of object proxy <(subclass of Ember.ObjectProxy):ember1458>: its 'content' is undefined."
Here is the json with the null relationship:
{"data": {
"attributes": {"name": "test-company"}, "id": "5",
"relationships": {
"address": {
"data": null
}
},
"type": "companies"
}
}
So how can I avoid this error? I could proof the model.address after fetching the company record if it has an id but doing this in every route isnt really smart.
Well initially your route model hook should make sure that organization has address with a valid ember-data record. If not, then create an empty one.
model: function(params) {
const store = this.get('store');
return Ember.RSVP.hash({
org: store.findRecord('orgnanization', params.id).then(org => {
org.get('address').then(address => {
if(Ember.isNone(address)) {
org.set('address', store.createRecrord('organization.address', {});
}
})
}),
});
},
Now your input can have direct binding to organization.address.street because it is now related to ember-data record at all times.
{{input type="text" value=model.org.address.street}}
And when editing You would first need to save address record, so it will have an id and then save the original organization.
editOrganization: function() {
const org = this.get('model.org')
const saveAddressPromise = org.get('address').then(address => {
return Ember.isPresent(address.get('street')) ? address.save() : EMPTY_PROMISE(null);
}); // If street is present save the address, other wise send empty promise that resolves to null
return saveAddressPromise.then(address => {
if(Ember.isNone(address) {
org.set('address', null); // The street is not present still. dont save address record
}
return org.save();
}).catch(sendError).finally(doSomething);
}
Another way would be to save an empty record everytime, then you would not have this .street check.
Nb! Empty_promise code example
return new Ember.RSVP.Promise(function(resolve, reject) {
resolve(value);
});
I am trying to implement MVC using AMD in canjs. For that I am using requirejs.
This is my domains.json file:
[
"1":{"uid": "1","urls": "domain1.abc.com"},
"2":{"uid": "2","urls": "domain2.abc.com"},
"3":{"uid": "3","urls": "domain3.abc.com"}
]
This is my domainModel:
define(['can'], function(can){
SearchModel= can.Model({
id: 'uid',
findAll: 'GET /domains.json'
},{})
return SearchModel;
})
This is my controller:
define(['can','jquery'],function(can,$){
domainController=can.Control({defaults:{view:"../view/search.hbs" }},
{
init : function(element,options){
this.element.html(can.view(this.options.view,{
searchlist : this.options.search
}))
}
});
return domainController;
}
This is my main js:
equirejs(['can','controller/domainController','model/domainModel'],
function(can, domainController,domainModel) {
var Application = can.Control.extend({
defaults :{ }
},{
init: function(element,options){
console.log('loaded');
domainModel.findAll({}, function(domains){
domainObject:{searchdomains : domains}
new domainController('#search',domainObject)
});
}
})
return Application;
});
I am tracing out my code.I put breakpoints.On model breakpoints I am not getting values in local variables in chrome devtools.
The url property has 'undefined/{id}' value and findAll method having four properties i.e. arguments,caller,length and name having a value null, null, 0 and "" respectively
I have checked my url of model by navigating through localhost on browser and it is correct.
Then why model cannot getting the values of json file?
You should get an error message since your data is not what Model expects for findAll. Your JSON should be an array (or at least have a length property):
[
{"uid": "1","urls": "domain1.abc.com"},
{"uid": "2","urls": "domain2.abc.com"},
{"uid": "3","urls": "domain3.abc.com"}
]
You also probably want to set the id property in you SearchModel to uid:
define(['can'], function(can){
SearchModel= can.Model({
id: 'uid',
findAll: 'GET /domains.json'
},{})
return SearchModel;
})
I am currently using StrongLoop as my API backend server and Mongodb as data storage engine.
Let's say there is a collection called article. It has two fields title, and content. And there are two frontend pages to display a list of articles and view a single article.
Obviously the data list page only need title field and the view page need both. Currently the GET method of StrongLoop API return all fields including content. It cost extra traffic. Is there any way that can just return specific field?
Mongodb support projection in find() method for this. How can I do the same thing by StrongLoop?
Have you taken a look at the filters offered. http://docs.strongloop.com/display/LB/Querying+models
Query for NodeAPI:
server.models.Student.findOne({where: {RFID: id},fields: {id: true,schoolId: true,classId: true}}, function (err, data) {
if (err)
callback(err);
else {
callback();
}
})
Query for RestAPI :
$http.get('http://localhost:3000/api/services?filter[fields][id]=true&filter[fields][make]=true&filter[fields][model]=true')
.then(function (response) {
}, function (error) {
});
You can use fields projections,
Sample Record:
{ name: 'Something', title: 'mr', description: 'some desc', patient: { name: 'Asvf', age: 20, address: { street: 1 }}}
First Level Projection:
model.find({ fields: { name: 1, description: 1, title: 0 } })
and I think Strong loop is not yet supporting for second-level object filter, does anyone know how to filter second-level object properties or is yet to implement?.
Second Level Projection: (Need help here)
Ex: 2
model.find({ fields: { name: 1, 'patient.name': 1, 'patient.age': 1, 'patient.address': 0 } })
// Which results { name } only
I have tried several things to query both the team member name and capacity in Rally developer depending upon iteration. One of the challenges I run into is that the team member name and capacity are under two different types. So, matching the team member names with the capacity has been a challenge.
One of my failed attempts in accomplishing this is as follows:
var queryConfig = {
key: "teamMember",
type: "User",
fetch: "UserName,Role",
query: '(TeamMemberships != "")'
};
var queryByUserName = {
key: "teamDataByUser", type: "UserIterationCapacity",
fetch: "Capacity,ObjectID",
query: rally.sdk.util.Query.or(ownerQueries)
};
You should be able to get the user's capacity and that users name in one query using dependent field fetching.
var queryByUserName = {
key: "teamDataByUser", type: "UserIterationCapacity",
fetch: "Capacity,ObjectID,User,DisplayName",
query: rally.sdk.util.Query.or(ownerQueries)
};
This query will return data that looks like:
{
ObjectID: 64265714,
Capacity: 6,
User: {
_ref: "https://rally1.rallydev.com/slm/webservice/x/user/1234.js",
ObjectID: 1234,
DisplayName: "Cindy"
},
_type: "UserIterationCapacity"
}