Loading data into Ext.Data.TreeStore - javascript

I am using ExtJs 4.1. We have one variable which contains data in JSON format. I want to load the value of that json into my Ext.Data.TreeStore. Usually store have loadData() which does the trick. But I do not see any such method for Ext.Data.TreeStore.
How can I load data into Ext.Data.TreeStore ?
Below is the definition of my store.
Ext.define('my.store.HStore', {
extend: 'Ext.data.TreeStore',
model: 'my.model.myModel',
autoLoad: false,
proxy: {
type: 'memory',
timeout: 90000,
url: '/data/',
reader: {
type: 'json'
}
}
});

Possible duplicates:
How to insert new record ( model ) in TreePanel?
How to update data with TreeStore or TreeEditor component?
Answer
To load data into a TreeStore after the store has loaded, you update the root node as per the documentation here: http://docs.sencha.com/extjs/4.1.0/#!/api/Ext.data.TreeStore-method-setRootNode
Also relevant and may help you: Treepanel with nested data from JSON
If you wish to append data to a TreeStore, well that is a bit more complicated... You must first locate the node that you wish to append a child to (e.g., store.getRootNode().findChildBy()) and add the child by either appendChild or insertChild depending on what best suits your use case.
findChildBy documentation: http://docs.sencha.com/extjs/4.1.0/#!/api/Ext.data.NodeInterface-method-findChildBy
appendChild Documentation: http://docs.sencha.com/extjs/4.1.0/#!/api/Ext.data.NodeInterface-method-appendChild
insertChild documentation: http://docs.sencha.com/extjs/4.1.0/#!/api/Ext.data.NodeInterface-method-insertChild
PS:
I have answered a few of your questions with no response, acceptance or comments. Please check the questions that you have asked, I'm more than happy to answer them however it is most beneficial to the entire community if you accept answers that you find helpful, or at least leave a comment if you need additional information. Thank you.

Related

How do I make multiple requests with an Ember adapter?

I'm building an Ember app with Parse as my backend. Parse out of the box does something odd with relationships – they only work one way. :/ I've been down the road of trying to manually make relationships work both ways by saving both models in Ember, but that seems messy and can mean that data gets out of sync quite easily. Yuck. So now I'm looking for alternatives.
First, let me explain in a bit more detail.
Let's say I have a post and comments. Parse will store the relationship from comments -> post, but not the other way around. Or, I can manage a list of comments in a 'Pointer array', but not the one-to-one relationship from comments -> post.
I see two options:
Modify the way the API works using their Cloud Code platform. This might be the easier route, but I'd rather address this in Ember so I can open source my adapter/serializer for others who run into this issue.
Figure out a way to make multiple requests in my adapter. I imagine it would work something like this:
a. this.store.findRecord('post', id) is called in the app code.
b. Ember adapter sees that post has a hasMany relationship based on what's defined in the model.
c. The adapter generates a url that looks for comments where the post's id matches the one I'm trying to find (pretty easy to do with Parse). Yes, this means multiple requests, but only 1 more (per relationship). It would be similar to what Ember does when there is a links attribute in the Payload, but we don't have that since Parse doesn't recognize the hasMany relationship`.
Looking for 2 things. First, any thoughts on if I'm thinking about this correctly, or suggestions on other options. Second, and probably most important, some ideas on what hook I can latch onto in my adapter to fire off a second request. My initial thought was something like this:
findRecord: function(store, type, id, snapshot) {
snapshot.eachRelationship(relationship => {
// Do something to build a url for each hasMany relationship
});
return Ember.RSVP.promise(...);
}
Any help with this is much appreciated.
So, basically you're trying to override the default findRecord behaviour of ember-data.
Your current approach sounds about right. You can create an adapter and provide custom definition to methods such as findRecord, findAll, query and so on.
A typical code example can be :
findRecord(store, type, id, snapshot) {
let data = {};
const traditional = true;
return new Ember.RSVP.hash({
news: Ember.$.ajax({ url: wpUrl + 'post', dataType: "jsonp", type: 'GET' }),
events: Ember.$.ajax({ url: wpUrl + 'comments', dataType: "jsonp", type: 'GET' })
});
});
The code snippet is completely vague, but i hope you got my point..

Dojo JsonRestStore with array not at root-level of JSON response

Is there a way to configure a JsonRestStore to work with an existing web service that returns an array of objects which is not at the root-level of the JSON response?
My JSON response is currently similar to this:
{
message: "",
success: true,
data: [
{ name: "Bugs Bunny", id: 1 },
{ name: "Daffy Duck", id: 2 }
],
total: 2
}
I need to tell the JsonRestStore that it will find the rows under "data", but I can't see a way to do this from looking at the documentation. Schema seems like a possibility but I can't make sense of it through the docs (or what I find in Google).
My web services return data in a format expected by stores in Ext JS, but I can't refactor years worth of web services now (dealing with pagination via HTTP headers instead of query string values will probably be fun, too, but that's a problem for another day).
Thanks.
While it's only barely called out in the API docs, there is an internal method in dojox/data/JsonRestStore named _processResults that happens to be easily overridable for this purpose. It receives the data returned by the service and the original Deferred from the request, and is expected to return an object containing items and totalCount.
Based on your data above, something like this ought to work:
var CustomRestStore = declare(JsonRestStore, {
_processResults: function (results) {
return {
items: results.data,
totalCount: results.total
};
}
});
The idea with dojo/store is that reference stores are provided, but they are intended to be customized to match whatever data format you want. For example, https://github.com/sitepen/dojo-smore has a few additional stores (e.g. one that handles Csv data). These stores provide good examples for how to handle data that is offered under a different structure.
There's also the new dstore project, http://dstorejs.io/ , which is going to eventually replace dojo/store in Dojo 2, but works today against Dojo 1.x. This might be easier for creating a custom store to match your data structure.

breezejs: adding referential constraint to an entity type

This is a follow-up question to my previous issue - this one was getting a bit messy and is more related to the Telerik Data Service.
The metadata I receive from the server are missing the referential constraints in the association node, although I've set the foreign key attribute on my model.
Therefore I was thinking about manually adding these constraints to my entities in the callback of FetchMetadata.
Is that possible and can someone provide a simple example on how to do it ?
[EDIT]
Here's what I have so far:
manager.fetchMetadata().then(function () {
var mandatType = manager.metadataStore.getEntityType("Mandate");
mandatType.autogeneratedKeyType = breeze.AutoGeneratedKeyType.Identity;
var openPositionsProp = new breeze.NavigationProperty({
name: "OpenPositions",
entityTypeName: "OpenPositions:#DirectDebitModel",
isScalar: true,
associationName: "OpenPosition_Mandate_Mandate_OpenPositions",
foreignKeyNames: ["Id"]
});
mandatType.addProperty(openPositionsProp);
});
But it raises the exception:
The 'Mandate:#DirectDebitModel' EntityType has already been added to a MetadataStore and therefore no additional properties may be added to it.
Ok, I have a possible approach that you might be able to use right now.
Fetch the metadata from Teleriks OData feed just like you do now.
Export the metadataStore created as a result of the previous step via the MetadataStore.exportMetadata method. This will return "stringified" json for the same metadata in Breeze's native format. This format is much easier to work with.
Convert this string to json via JSON.parse.
Modify the json to add referential constraint information. See Breeze Native Metadata format docs here
Create a new MetadataStore and import the modified json into it.
Create a new EntityManager with this MetadataStore and use it. This EntityManager should now have complete Breeze metadata for use with the rest of the feed.
Hope this makes sense!
We are planning on releasing a form of hybrid metadata in the next release. Unfortunately, it doesn't cover your case because we are focusing on how to add custom metadata to an existing metadataStore, and not actually edit/modify the existing metadata.
Another alternative is that we (IdeaBlade) do offer consulting for this type of work. We could probably write a tool that does steps 1 thru 6 for you. Please contact breeze#ideablade.com if this is of interest and mention this post.
So you are getting meta data but it doesn't have a relationship between the entities. Hmm I have not gotten metaData AND tried to create additional model properties that are related.
Your best bet is to add a property that is a navigation type on the constructor.
http://www.breezejs.com/sites/all/apidocs/classes/EntityType.html#method_addProperty
If it were me, I would try it this way (or something similar) inside of the constructor -
myEntity.addProperty({
associatedEntity: {
entityTypeName: "AssociatedEntity", isScalar: true,
associationName: "AssociatedEntity_MyEntitys", foreignKeyNames: ["associatedEntityId"]
}
});
Where myEntity is the name of the current entity, AssociatedEntity would be your navigation property, the associatedEntityId is a property of myEntity that refers to the other entity. Of course to have this be a two-way relationship you would need to add a property to AssociatedEntity as well.
associatedEntity.addProperty({
myEntitys: {
entityTypeName: "MyEntity", isScalar: true,
associationName: "AssociatedEntity_MyEntitys", foreignKeyNames: ["myEntityId"]
}
});

Optimal URL structure for Backbone.js and Backbone implementation

I'm developing a RESTful API for a Quiz app, which is going to be built with Backbone.js and Marionette. I'm quite new to backbone and was wondering what de best URL structure would be. I have the following resources:
Answer,
Question which contains Answers,
Question Group which contains Questions,
Quiz which contains Question Groups.
Two possible URL structures come to mind:
GET /quizzes/:id
GET /quizzes/:id/questiongroups
GET /quizzes/:id/questiongroups/:id
GET /quizzes/:id/questiongroups/:id/questions
GET /quizzes/:id/questiongroups/:id/questions/:id
GET /quizzes/:id/questiongroups/:id/questions/:id/answers
or:
GET /quizzes/:id
GET /quizzes/:id/questiongroups
GET /questiongroups/:id
GET /questiongroups/:id/questions
...
Now, I have been trying to use both of these options. With the first one, I can't figure out how to define the collections as a property of the parent models in Backbone so that I can use fetch() on them. The problem with the second option is a bit different: as I understand it, Backbone derives the url for a model from its collection, but the collection is a child of another resource, whereas the url for getting a single resource uses another collection, namely the global set of resources.
I'm pretty sure I'd have to override url() in both cases. I tried some things but didn't come up with anything useable at all. Also, I'd rather not override every single url()-model in the app, changing the API structure to suit the preferences of Backbone seems like a better option to me.
Any pointers as to what seems the right way to do it with Backbone would be great!
Thanks
If questiongroups can only appear in a single quiz, then the first option (the hierarchical one) is an obvious choice. To comply with RESTful conventions, you might want to consider using singular nouns instead: /quiz/:id/questiongroups/:id/question/:id/answer/:id
To solve your fetching problem, I would recommend using nested backbone models as per this answer: https://stackoverflow.com/a/9904874/1941552. I've also added a cheeky little parentModel attribute.
For example, your QuizModel could look something like this:
var Quiz = Backbone.Model.extend({
urlRoot: '/quiz/', // backbone appends the id automatically :)
defaults: {
title: 'My Quiz'
description: 'A quiz containing some question groups.'
},
model: {
questionGroups: QuestionGroups,
},
parse: function(response){
for(var key in this.model){
var embeddedClass = this.model[key];
var embeddedData = response[key];
response[key] = new embeddedClass(embeddedData, {
parse:true,
parentModel:this
});
}
return response;
}
});
Then, your QuestionGroups model could have the following url() function:
var QuestionGroups = Backbone.Model.extend({
// store metadata and each individual question group
url: function() {
return this.parentModel.url()+'/questiongroup/'+this.id;
}
});
Alternatively, if you don't need to store any metadata, you could use a Backbone.Collection:
var QuestionGroups = Backbone.Collection.extend({
model: QuestionGroup,
url: function() {
return this.parentModel.url()+'/questiongroup/'+this.id;
}
});
I'm afraid I haven't tested any of this, but I hope it can be useful anyway!

What is the significance of this 'load' method in extjs?

For the listeners part of this data store in sencha touch, what exactly does the 'load' event mean? I searched the api documentation but was unable to find an explanation in the data store section nor the observable class section.
new Ext.data.Store({
model: "",
proxy: {
type: "ajax",
url : "/search/json/",
reader: {
type: "json",
root: "searchResult"
}
},
listeners: {
load: myapp.results //Note: myapp.results is a function defined elsewhere
}
});
As an additional note, if anyone knows of a reference which lists all of the listener 'eventnames' such as load, and their significance I would be grateful if they would be so kind as to post them here. (The sencha documentation only says: 'The name of the event to listen for. May also be an object who's property names are event names. See' and ends at See )
Sencha API says "Fires whenever the store reads data from a remote data source." There is all different event-names too. Am I missing something?
This event is fired when the data is loaded.
You must assign a function to use it.
listeners:{
load:function(store,records,options){
// Do stuff, you can access here to the loaded store, the loaded records and options
}
}
It will be called each time the data is loaded, on refresh, on page change, etc.
Consider two components that is one is dependent upon another component which is to used as input by it in such a case we can make use of load function.

Categories