I am trying to directly map API response to my Redux-Orm models. I have two models:
Product hasMany ProductProperties
ProductProperty belongsTo Product
The API response I receive is:
{
products: [
{name: 'P1', id: 1},
{name: 'P2', id: 2}
],
product_properties: [
{name: 'Test1', id: 10, product_id: 1},
{name: 'Test2', id: 11, product_id: 1},
{name: 'Test3', id: 12, product_id: 2}
{name: 'Test4', id: 13, product_id: 2}
]
}
I can tweak the API response to match with the redux-orm.
My Question is:
I want to avoid doing ProductProperty.first().set({product: Product.first}) -- That is I don't want to set the associations (child records) explicitly and have redux-orm infer them automatically.
Is there some way I can specify the foreign key that redux-orm can look for?
What I recommend to you is to use a json api standard for your API.
That way, in your API return, your products would have a relationships key that will help you map it to the included product_properties. Something like:
{
data: [
{
type: 'product',
id: 1,
name: 'P1',
relationships: [
product_property: [
{
data: {type: 'product_property', id: 10}
},
{
data: {type: 'product_property', id: 11}
}
]
]
},
{
type: 'product',
id: 2,
name: 'P2',
relationships: [
product_property: [
{
data: {type: 'product_property', id: 12}
},
{
data: {type: 'product_property', id: 13}
}
]
]
}
],
included: [
{type: 'product_property', name: 'Test1', id: 10},
{type: 'product_property', name: 'Test2', id: 11},
{type: 'product_property', name: 'Test3', id: 12}
{type: 'product_property', name: 'Test4', id: 13}
]
}
That way, it would be much easier for you to make a standard API parser that would map your json api resources to your redux-orm store. You create a redux-orm resource for each product and each product_property. Than you loop over product relationships and link them.
Hope that would help.
Best
Related
I'm trying to figure out how to get the time when the transaction was included in block by it's hash on the P-Chain.
I looked into getTx method but the response doesn't include this information:
{
unsignedTx: {
networkID: 5,
blockchainID: '11111111111111111111111111111111LpoYY',
outputs: [],
inputs: [ [Object] ],
memo: '0x44656c656761746564207769746820466967656d6e74277320536c61746520415049',
validator: {
nodeID: 'NodeID-4B4rc5vdD1758JSBYL1xyvE5NHGzz6xzH',
start: 1658162594,
end: 1658252280,
weight: 1000000000
},
stake: [ [Object] ],
rewardsOwner: { addresses: [Array], locktime: 0, threshold: 1 }
},
credentials: [ { signatures: [Array] } ]
}
All normalizr examples are focused on nested objects they are expecting an API result that looks like this:
{
id: 1,
title: 'Some Article',
author: {
id: 1,
name: 'Dan'
}
}
But I actually found that the following format where you have to do the collections joins yourself is the one I'm dealing with the most, can I use normalizr to handle this case for me?
Posts [{ _id: 1, name: 'post text 1', userId: 5, locationId: 8}]
Locations [{ _id: 8, name: 'New York'}]
Users [{ _id: 5, name: 'John Doe', country: 'US'}]
expected result:
{
results: [1], // posts ids
entities: {
posts: {
1: { name: 'post text 1', userId: 5, locationId: 8 }
},
users: {
5: { name: 'John Doe', country: 'US' }
},
locations: {
8: { name: 'New York' },
}
}
}
Docs/github issues nothing mentions it as far as I could find
I have a very standard nested JSON response. Projects have many dashboards. Dashboards have many charts.
What is the right way to define and use my schemas?
Below is the code for my Schemas.js, my API response, and what Normalizr converts my API response into.
Schemas.js:
import { Schema, arrayOf, normalize } from 'normalizr';
// Create a schema for each model.
const project = new Schema('projects');
const dashboard = new Schema('dashboard');
const chart = new Schema('chart');
// Projects have many dashboards.
project.define({
dashboards: arrayOf(dashboard)
});
// Dashboards have many charts.
dashboard.define({
charts: arrayOf(chart)
});
export const Schemas = { project, dashboard, chart };
My API response:
{
projects: [{
id: 1,
name: "Project 1",
dashboards: [{
id: 1,
name: "Dashboard 1",
charts: [{
id: 1,
name: "Chart 1"
},
{
id: 2,
name: "Chart 2"
}]
},
{
id: 2,
name: "Dashboard 2",
charts: [{
id: 3,
name: "Chart 3"
},
{
id: 4,
name: "Chart 4"
}]
}]
},
{
id: 2,
name: "Project 2",
dashboards: [{
id: 3,
name: "Dashboard",
charts: []
}]
}]
}
When I receive this JSON in an action I do normalize(response, Schemas.project);. This seems to move the entire response into entities.projects.undefined.
{
entities: {
projects: {
undefined: {
projects: [{
id: 1,
name: "Project 1",
...
}, ...]
}
}
},
result: undefined
}
How should I correctly define and use my schemas for this?
References:
https://github.com/gaearon/normalizr
https://github.com/reactjs/redux/blob/master/examples/real-world/actions/index.js
This should give you the desired result:
normalize(response, {
projects: arrayOf(Schemas.project)
});
The projects key is nescessary because you have an extra key in your response, and the arrayOf() indicates that the API returns an array of results.
I have a meteor app using livestamp. However, I wish to represent a collection within a reactive-table. However, when I try the code below, it doesn't work (I see nothing in the updated column):
Template.sensor_table.helpers
settings: () ->
return {
collection: Sensors
rowsPerPage: 100
showFilter: true
fields: [
{ key: '_id', label: 'id' },
{ key: '_id', label: 'rack', fn: (v,o) -> (getSensor v).rack },
{ key: 'temp', label: 'temperature (degC)' },
{ key: 'ts', label: 'updated', fn: (v,o) -> livestamp v }
]
}
but when I use it within a template, it works fine. How can I get the functionality of livestamp within my reactive table?
You can do that with https://atmospherejs.com/aldeed/tabular it's also datatables but it's different package (in my opinion better)
if you choose to use it here is an example, tabular has the option to render fields as a template and livestamp should work just as on the template itself.
TabularTables.Books = new Tabular.Table({
name: "Books",
collection: Books,
columns: [
{data: "_id", title: "id"},
{data: "_id", title: "Rack"},
{ data: 'ts', title: 'updated',
tmpl: Meteor.isClient && Template.liveStamp
}
]
});
// template
<template name="liveStamp">
<p>{{livestamp this.ts}}</p>
</template>
so i guess it helps to actually read the manual....
Template.sensor_table.helpers
settings: () ->
return {
collection: Sensors
rowsPerPage: 100
showFilter: true
fields: [
{ key: '_id', label: 'id' },
{ key: '_id', label: 'rack', fn: (v,o) -> (getSensor v).rack },
{ key: 'temp', label: 'temperature (°C)' },
{ key: 'ts', label: 'updated', tmpl: Template.sensor_updated }
]
}
and then a template somewhere...
<template name="sensor_updated">
{{ livestamp ts }}
</template>
I am attempting to add a List component to a view in Sencha Touch. The app runs correctly until I try to add the list component. After Adding the list to the view the app loads (shows the splash screen)then only shows a white screen.
I'm using Sencha Touch, XCode 4, iOS 5 SDK, and PhoneGap 1.3.0.
Thanks in advance!
here's the code for the view:
plantanalyzer.views.BuildingList = Ext.extend(Ext.Panel, {
dockedItems: [{
dock: 'top',
html: '<img src="images/logo.jpg"/>'
},
{
xtype: 'list',
itemTpl : '{name}',
grouped : true,
indexBar: true,
store: newStore
}]
});
and the code for my test datastore. I have this in the head of index.html:
var newStore;
function onBodyLoad(){
Ext.regModel('Plants', {
fields: ['name', 'efficiency']
});
newStore = new Ext.data.JsonStore({
model : 'Plants',
sorters: 'name',
getGroupString : function(record) {
return record.get('name')[0];
},
data: [
{name: 'Milwaukee', efficiency: .85},
{name: 'New York', efficiency: .65},
{name: 'St Paul', efficiency: .73},
{name: 'Phoenix', efficiency: .35},
{name: 'Los Angeles', efficiency: .45},
{name: 'Miami', efficiency: .75},
{name: 'London', efficiency: .39},
{name: 'Moscow', efficiency: .95},
{name: 'Hogwarts', efficiency: .99}
]
});
}
You create your store on body load, i.e. after the list was loaded so the newStore object is empty when the list needed.
Put this code:
Ext.regModel('Plants', {
fields: ['name', 'efficiency']
});
newStore = new Ext.data.JsonStore({
model : 'Plants',
sorters: 'name',
getGroupString : function(record) {
return record.get('name')[0];
},
data: [
{name: 'Milwaukee', efficiency: .85},
{name: 'New York', efficiency: .65},
{name: 'St Paul', efficiency: .73},
{name: 'Phoenix', efficiency: .35},
{name: 'Los Angeles', efficiency: .45},
{name: 'Miami', efficiency: .75},
{name: 'London', efficiency: .39},
{name: 'Moscow', efficiency: .95},
{name: 'Hogwarts', efficiency: .99}
]
});
Right before:
plantanalyzer.views.BuildingList = Ext.extend(Ext.Panel, {
dockedItems: [{
dock: 'top',
html: '<img src="images/logo.jpg"/>'
},
{
xtype: 'list',
itemTpl : '{name}',
grouped : true,
indexBar: true,
store: newStore
}]
});
To check if this is really the case.
One other suggestion is that you should put the list in the items of the panel, not the dockedItems.
Btw, your code is not well structured. You should follow the MVC patter.
Check this https://vimeo.com/17705448 and this http://www.sencha.com/learn/a-sencha-touch-mvc-application-with-phonegap/.