I am trying to create a big request for most of the page data. A certain model has polymorphic relations to a few other models, which in turn have normal relations to other models. What I am trying to achieve is fetch those "sub-relations" along with the polymorphic objects. Something like:
filter = {
include: [{
canvas: {
points: {
device: [
{
relation: 'chart',
scope: {
where: {
type: 'line',
},
},
},
'model',
],
},
}
}],
}
As displayed under the device (which is the polymorphic relation attribute), I also include two relations, chart and model. Those relations only exist in one type of device chartDevice, and if the query fetches such rows, it works. However, if the query fetches other types, e.g. networkDevice, which does not include such relations, it crashes.
Also, if I try to include a relation specific to networkDevice, it doesn't work.
I guess Loopback might not support that in polymorphic relations, but I am curious if there is any workaround that I might have not thought of.
Related
I have a nested json data, namely:
{
name: 'alex',
tel: {
personal: '347xxxx',
work: '331xxxx'
}
}
Then the following model:
Ext.define("Employer", {
extend: 'Ext.data.Model',
idProperty: 'personalTel',
fields: [...
{name: 'personalTel', mapping: 'tel.personal'}
Finally the following store:
Ext.create('Ext.data.Store',{
model: 'Employer',
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'root'
}
},
data: myInitialData //an array containing json objects
As long as the data is contained in myInitialData the personalTel field is correctly set.
However, adding a new record to the store does not trigger the mapping and so I find myself with strange personalTel property, that is automatic IDs extjs puts!
ExtJS allows you to load multiple models via nesting when using a reader. It does not allow those models to be created when instantiating the model directly, which is what adding the object to the store does.
The idea is that each model is treated separately with its own store. Want to add a customer with a telephone number? Create the telephone number first, put it in its store, then create the customer with a reference to the telephone number.
This approach is a bit clumsy, though, and only works with models that really are separate entities.
An alternative approach would be to use a custom type, or simply to use the 'auto' type (which treats the data as a blob that you can do what you want with). Both approaches have their drawbacks.
When I create a model using Ext.create() in ExtJs 4.2+, I am expecting the mapping to fill the model but it does not seem to do it. Is it a normal behavior?
If I use a model with mapping in a store, the mapping works fine...
Example not working:
http://jsfiddle.net/B6v6v/
Ext.define('MyApp.model.file', {
extend: 'Ext.data.Model',
fields: [
{
name: 'name',
mapping:'label'
}]
});
var rec = Ext.create("MyApp.model.file",{"label":"TEST"});
console.log(rec.get("name"));
Yes, it's normal. The mapping is for transforming data coming in from the server into something readable in your model. If you already have the data, why not just use the correct key?
If you must, you can do something like:
MyApp.model.File.getProxy().getReader().readRecords([{}, {}, {}]);
I am trying to create a backbone client side application. I am receiving a list of json objects from the server on startup that will be a list of the possible tables exposed from the server, with their structure. E.g. Customers, Orders, Invoices, Employees
I want to create the models, collections and views dynamically based on the data I receive from the server.
Only when I receive the json on load will I know what the models should be and what the relationships between the models should be.
E.g. Customers structure might be Id, CustomerName, Address, Contact Numbers.
Order Structure might be Id, CustomerId, OrderDate, Amount
etc
By building Models, collections, views, controllers dynamically, I could in theory on startup point at another server who might give me a totally different set of tables e.g. : Movies, Actors etc.. with their structures.
Also, if additional fields are added I don't have to change the client side code again. E.g. Customer table might include a new field called ContactPerson
Please assist me as all the examples I saw on backbone is all based on statically defining the models on the client side up front. So create a model and collections and views for Customers, Orders, Invoices, Employees etc. etc.
Best wishes,
Andy
As already mentioned in the comments, Backbone models are dynamic by nature. So this is perfectly valid for example:
// A example dataset, this could be returned as JSON from the server
var jsonDataA = [
{
name: "Foo",
title: "Bar"
},
{
name: "a",
title: "b"
}
],
// A different example dataset
jsonDataB = [
{
make: "X",
model: "Y"
},
{
make: "Z",
model: "ZZ"
}
],
MyModel = Backbone.Model.extend({
/* Empty Model definition */
}),
MyCollection = Backbone.Collection.extend({
model: MyModel
}),
collection = new MyCollection();
collection.reset(jsonDataA);
console.log(collection.models);
collection.reset(jsonDataB);
console.log(collections.models);
Here I have reused the same Collection and Model definition to store completely different datasets.
One part is the raw data, the other part is its relations. You need to transport the metadata also, which contains the types and their relations. Model attributes will be populated automatically.
From your metadata a simple object can be constructed, where the keys describe one entity, for example:
var entites = {};
entities["Customer"] = Backbone.Model.extend({
/* Model definition based on metadata */
});
var parametersFromServer = {name: "John Doe"};
var customer = new entities["Customer"](parametersFromServer);
For building relations I would recommend using BackboneRelational plugin.
i'm writing a backbone.js 'app', and would like to map the json output of graphite/carbon directly to some backbone models/collections.
in general, the json output is something like this:
[
{
'target': 'some.string.1',
'datapoints': [ [ val1, timestamp1 ], [ val2, timestamp2 ]... ]
},
{
'target': 'some.string.2',
'datapoints': [ [ val1, timestamp1 ], [ val2, timestamp2 ]... ]
},
...
]
i have defined a simple model and collection such that:
class Measurement extends Backbone.Model
defaults:
id: undefined
val: undefined
class Measurements extends Backbone.Collection
model: Measurement
initialize: (model, options) ->
if options.metric
#metric = options.metric
url: ->
'/?target=' + #metric
parse: (data,xhr) ->
if _.size(data) == 1
return _(data[0]['datapoints']).map( (d) ->
m = {}
m['id'] = new Date(0)
m['id'].setUTCSeconds( d[1] )
m['val'] = d[0]
m
)
undefined
as you can see, i overload the id to be the timestamp of each Measurement and all measurements for a specific 'metric' is stored under a Collection called Measurements.
i've also hardcoded it so it really only works for one Measurements Collection (ie the 'target' in the json).
my question concerns how best/elegant/flexible to implement the gathering of multiple Measurements (the collection) in a single call. ie graphite supports the use of wildcards for its 'targets' so that an ajax request to /?target=some.string.* would bring back all matching targets and datapoints (like in the json example). i would then present this to a View where i would render say cumulative data or plot all of the Measurements against time.
i was thinking of using another Collection (lets call it a Set) that would contain many Measurements. I would like to be able to do something like Set.fetch() to get all the matching Measurements from the server and have the Set create many Measurements Collections from the single ajax request.
does anyone have any suggestions of how to implement this? or even a better way of representing this model/collection layer?
whilst not directly answering your question - have you looked at graphene? - it's a javascript dashboard for graphite and it's using backbone.js. You might see how it was implemented there and borrow/steal some ideas.
As a side note - from my experience building a different beast (giraffe, sorry for the plug, but it's important to give context), there are some difficulties matching wildcard targets with graphite. The main reason is that you don't know how many targets are returned. This can be tricky when, for example, you want one of those targets to have a red colour on the graph, or want to add a target like an annotator (to draw as infinite to mark a time-based event). Just something to bear in mind when working with wildcards and multi-target requests with graphite.
The specific example would be a "preferences" window that has a series of tabs, each of which contains a series of form fields. None of these tabs or form fields would be reused outside of the window, and there would only ever be one instance of the window itself. Using a single item config means it's hundreds of lines long, making it hard to maintain.
My.Ns.PreferencesWindow = Ext.extend(Ext.Window, {
items: [
// A tab
{
items: [
// Form fields
{},
{},
{},
]
},
// A tab
{
items: [
// Form fields
{},
{},
{},
]
},
...
]
});
I am not asking how to organize a large ExtJS application. I have read Best Way to Organize an ExtJS Project and Saki's blog posts on the topic.
It doesn't really make sense to Ext.extend for each of the items, because they're not going to be instantiated more than once.
Encapsulating the various components in "generator" functions that just return an item's json seems at first glance to be a reasonable approach.
Just use variables to make it more readable:
var tabOneCfg = {
items: [
// etc.
]
};
var tabTwoCfg = {
items: [
// etc.
]
};
My.Ns.PreferencesWindow = Ext.extend(Ext.Window, {
items: [
tabOneCfg,
tabTwoCfg
]
});
You can make it as granular as you want, and even include the sub-configs in separate files (although that type of scheme would not play well with dynamic loading under Ext 4). A generator or factory function could make sense as well, depending on the nature of the configs. In principle it's the same thing either way -- just break the sub-configs into smaller chunks and use them as needed.