I'm trying to determine the best method for pre-processing JSON for usage in an EXTJS TreeGrid. It's my understanding that EXTJS is expecting JSON to be formatted in the following manner:
{
"text":".",
"children": [
{
Location:'New Jersey',
iconCls:'task-folder',
expanded: true,
children:[
{
Building:'North-west Building',
iconCls:'task-folder',
children: [
{
Computer: '#12345',
Owner: 'Tommy Maintz',
iconCls: 'task',
leaf: true
},
{
Computer: '#98776',
Owner: 'Robert Maintz',
iconCls: 'task',
leaf: true
}
]
}
]
}
]
}
Unfortunately, the data source I am working with outputs flat JSON as such:
{
Computer: '#12345',
Owner: 'Tommy Maintz',
Building:'North-west Building',
Location:'New Jersey'
}
{
Computer: '#98776',
Owner: 'Robert Maintz',
Building:'North-west Building',
Location:'New Jersey'
}
What EXT methods are at my disposal to pre-process my JSON to work with a TreeGrid?
There is no built-in function/method that would do what you want, hence a coding is inevitable. Some advices:
You wouldn't work with the string but you would use var o = Ext.decode(json); to convert the raw json to object o
You can use Ext.each() to iterate through the resulting array or object
I'd write a recursive routine that would construct the resulting nested object
When you have the object with the desired structure you can use tree.setRootNode(result) to populate the tree.
Related
I have an database full of objects that contain information, as well as other arrays of objects. I would like to change the inner arrays to only be arrays with each index as an ObjectId type with their respective ObjectId
I am using the mongoose populate function to retrieve this information later in the program. So only the ObjectId is needed for the reference.
job {
_id: 1,
name: "name",
parts: [
{ _id: ObjectId("5c790ce7d3dc8d00ccc2688c"), name: "name"},
{ _id: ObjectId("5c790ce7d3dc8d00ccc2688b"), name: "name"},
{ _id: ObjectId("5c790ce7d3dc8d00ccc2688a"), name: "name"},
]
}
Desired Result
job {
_id: 1,
name: "name",
parts: [
ObjectId("5c790ce7d3dc8d00ccc2688c"),
ObjectId("5c790ce7d3dc8d00ccc2688b"),
ObjectId("5c790ce7d3dc8d00ccc2688a")
]
}
I tried a few mongoDB queries from the command line but none of them are quite giving the result I need. This one has no errors, but it doesn't seem to change anything.
db.jobs.update(
{},
{
$set: {"parts.$[element]": "element._id"}
},
{
multi: true,
arrayFilters: [{ "element": {} }]
}
)
I'm not sure if this is possible or not using only the mongo shell.
Mongo v4.2 introduced pipelined updates this allows the use of aggregation operators within the update and more importantly updating a document using it's own values. which is what you want to achieve.
db.jobs.updateMany(
{},
[
{
'$set': {
'parts': {
'$map': {
'input': '$parts',
'as': 'part',
'in': '$$part._id'
}
}
}
}
]);
Unfortunately this is not possible for earlier Mongo versions. Specifically $arrayFilters allows you to filter an array but again prior to the new update syntax accessing own values within the update is not possible.
You'll have to iterate over all documents and do the update one by one in code.
As #Tom Slabbaert mentioned in the other answer you will have to use updates with aggregation pipelines available from v4.2 if you want to update the documents in bulk in one operation.
As an alternative to using $map, if you want only a single value at the top level and the value is accessible using the dot notation. You can simply use $set with the dot notation.
db.jobs.updateMany({}, [{
$set: { parts: "$parts._id" }
}])
Need help with el-dropdown to parse contents from express parsed json.
Tried https://medium.com/html-all-the-things/hatt-vue-js-2-9b34557f0305 this tutorial and seems there is no option to parse contents from JSON.
/*dropdown in index.vue, simplified*/
<el-dropdown>
<el-button type="primary" trigger="click">dropList<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu>
<el-dropdown-item command="someCommandWhichIsNotYetWritten">{{getList}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
/*script*/
export default {
data() {
return {
getList: []
}
}
/*The returning JSON is as follows*/
result {
metaData: [ { name: 'NAME' } ],
rows: [
{ NAME: '131' },
{ NAME: '132' },
{ NAME: '138' },
{ NAME: '139' },
{ NAME: '142' },
{ NAME: '193' },
{ NAME: '194' },
{ NAME: '235' },
{ NAME: '241' },
{ NAME: '44' }
]
}
PS: I know these comment lines doesn't work in all cases. Just added to clarify to what I did.
In this code I see all the contents of JSON, but I want to list those numbers (NAME) individually which connects to a command(a href) or something.
PS: As I understand el-dropdown command="someCommand" is similar to <a href> or something.
When your data is loaded you need to assign it to a local component data, f. e:
this.getList = result.rows
Dropdown items have to be created in a loop (read more about v-for directive in vue docs):
<el-dropdown-item #command="todo(item)" v-for="item in getList" :key="item. NAME">{{item.NAME}}</el-dropdown-item>
To handle command from piece of code above you'd have to create local method named todo.
I have what I think is a very simple issue, but I just don't get how to do this data manipulation. This sadly didn't help, even though it's the same pain I am feeling with Ember.
Here is a route:
route/dashboard.js:
import Ember from 'ember';
export default Ember.Route.extend({
// this is for testing, normally we get the data from the store
model: function() {
return this.get('modelTestData');
},
modelTestData: [{
name: 'gear',
colorByPoint: true,
data: [
{y: 10, name: 'Test1'},
{y: 12, name: 'Test2'},
{y: 40, name: 'Test3'}
]
}],
});
The structure of the 'modelTestData' object has to be exactly like that as it is passed into a child component that needs it structured that way.
I can easily get my data from the API and put it into the model:
model: function() {
return this.store.get('category');
},
But then I need to restructure it...but how?
I have to somehow iterate over the categories collection and extract parts of data from each record to replace the 'data' part of the modelTestData object.
So I have 3 issues I am completely stumped on:
How to 'get at' the attributes I need from the model?
How to structure them as an array of objects with 'y' and 'name'?
How to assign that structure to the 'data' property of modelTestData instead of it being hardcoded?
Categories is a JSONAPI object like this:
{
"data":[
{
"id":"1",
"type":"categories",
"attributes":{
"name":"Carrying system",
"total-grams":"0.0"
}
},
{
"id":"2",
"type":"categories",
"attributes":{
"name":"Shelter system",
"total-grams":"0.0"
}
}
]
}
I need to map the grams value to 'y' and the name to 'name' in modelTestData.
Note that the category data is used in other routes for other purposes exactly as returned by the API. So I don't want to change the model structure itself, or what the API returns...that will break other parts of the app that do use 'category' in its original structure.
This is a specific use case that this route needs to massage the data to pass to the child component as per the structure of modelTestData.
I also wonder whether this data manipulation task belongs in a route?
Should I somehow do this in the serliazer adapter, creating a new structure as say 'categoryWeights' so I can then do:
model: function() {
return this.store.get('categoryWeights');
},
EDIT
I have managed to do this in the route, but it just gives me an array of objects. I need a single object containing 2 properties and an embedded array of objects.
model() {
return this.store.findAll('category')
.then(categories => categories.map(category => {
let data = {
y: category.get('totalGrams'),
name: category.get('name')
};
return data;
}))
},
This should probably go into a computed property:
dataForSubModel: Ember.computed('model.#each.totalGrams', 'model.#each.name', {
get() {
return [{name: 'gear', colorByPoint: true, this.get('model').map(m => ({y:m.get('totalGrams'), name:m.get('name')}))}
}
}),
The serializer is the wrong place, because its not that you need to convert it between the server and your app, but between your app and a strange component.
Actually the best thing would be to refactor the component.
Ok I got this to work in the route.
model() {
return this.store.findAll('category')
.then( function(categories) {
let data = [];
data = categories.map(category => {
return {
y: category.get('totalGrams'),
name: category.get('name')
}
});
return [{name: 'gear', colorByPoint: true, data}];
})
},
I still have the feeling this should be done in the adapter or serializer. Would be happy to see answers that show how to do that.
I'm looking to use json from Github's issues api with Ember Data.
The problem is that the return json is not formatted the way ember data wants it to be.
Github returns data as such.
[
{id: 0, title: 'test'},
{id: 1, title: "ect.."}
]
Where as Ember Data's RestAdapter expects it to be like:
{ issues: [
{id: 0, title: 'test'},
{id: 1, title: "ect.."}
] }
I assume based on some research that I need to override the Find and FindAll methods for the DS.RestAdapter
MyApp.Issue = DS.Model.extend({ ... });
MyApp.IssueAdapter = DS.RESTAdapter.extend({
host: 'https://api.github.com/repos/emberjs/ember.js',
find: function(store, type, id) {
...
},
findAll: function(store, type since) {
...
},
}
The problem is in the example if found there are a few out of data methods and it also does not explain how I can pass a array with out an key of "issues"
To be honest I'm really a complete noob to all this and most of this js is over my head but I feel like I'm close to figuring this out. Let me know if I'm on the right track.
I am creating a tree in ExtJS 3.4.0. I understand the JSON the component is expecting should be returned like this:
[{
id: 1,
text: 'Brian',
leaf: true,
checked: false
}]
but the JSON that i am getting retrurned to me has a root node like this:
{"message":
{"nodes":
[{
"text":"Brian",
"id":"1",
"leaf":true,
"checked":false
}]
}
}
I don't see a way to specify in my configuration where in the JSON, the actual tree data is. Is this even possible? I see a "root" paramater, but that is different. Is there a way to specify where in the incoming JSON to "start" from.
Oh and I don't have control over the incoming JSON or obviously I would just change the JSON. :-)
Thanks
I think you could do something like along these lines (from looking at the ext docs):
var treePanel = {
xtype: 'treepanel',
loader: new Ext.tree.TreeLoader(),
root: new Ext.tree.TreeNode({
expanded: true,
children: myJsonObject.message.nodes
})
}
The is a 'root' option in the reader for your Store's Proxy that you can use.
proxy: {
reader: {
type : 'json',
root : 'nodes'
},
// Other configs
}