I am a bit new to d3.js, but I'm having quite a bit of fun with it. So far, I have implemented a force-directed graph that is very close to many of the examples and tutorials out there.
Direct Concern
Like many of the examples, I have a JSON structure like this:
{"nodes": ["node1", "node2", ... ],
"links": [{source: 0, target: 1, "field1": 5, ...}, ... ]}
However, I think that it would be easier to construct my data sources like this:
{"links": [
{source: "node1", target: "node2", "field1": 5, ...},
{source: "node2", target: "node4", "field1": 1, ...},
{source: "node3", target: "node4", "field1": 8, ...}
]}
Instead of explicitly defining the nodes in my graph, they are implicitly defined in the link structures.
The Reason
I wanted to list the eventual goal of the project in case someone had some specific example code or idiomatic way of doing this of which I am unaware.
The goal for the project would eventually be a graph that is updating in real-time. The back-end is being developed and is subject to some change and revision.
At the moment, I'm imagining pulling down an update JSON feed every X seconds and updating the structure of that graph with the new information. The pulled feed would only contain the updated structures of the graph, so the script would need to maintain the all of the already pulled nodes and links and add any new ones, if necessary.
Thanks!
I apologize if this has been asked before. I did some searching and didn't find anything. Feel free to insult and berate me if I missed it.
I've had to do this a few times. The simplest approach I've found has been to simply compute the set of nodes base don the list of links and then turn it into an array for the force graph to use:
var links = [ .... ];
var nodeMap = {};
links.forEach(function(d, i) {
nodeMap[d.source] = true;
nodeMap[d.target] = true;
});
var nodes = [];
for (key in nodeMap)
nodes.push(key);
d3.layout.force()
.nodes(nodes)
.links(links);
I've done just this in the example "D3 Based Force Directed Radial Graph". I do this because I want to understand how the data is used, internally, independent of structures like JSON and CSV, which can always be layered in, later.
Anyhow, I hope the example helps you.
My Best,
Frank
Related
I have a power app that wants to collect some data from a rest API, I am using Flow as this seems to be the recommended way.
I have a collection:
[
{id: 1,name: "test",lines: [
{id: 244,
StrategyId: 1,
TypeId: 0,
Weight: 10,
toWeight: 200
}
]
},
{id: 3,name: "test2",lines: [
{id: 262,
StrategyId: 3,
TypeId: 0,
Weight: 0,
toWeight: 200
}
]
}
]
When I enter this into a formula straight up, it works fine:
ClearCollect( CityPopulations, json...)
However, when I try to fetch the data from Flow it only returns a collection with one single entry that is the json data as string.
Set('CityPopulations','PowerApp->Sendmeamobilenotification'.Run());ClearCollect(NewTable, CityPopulations.testoutput);
In Microsoft flow I use PowerApps trigger and Respond to PowerApps.
Also note that there are no " on the propertynames in json structure, but this was the only way I could get Power Apps to actually accept typing in json manually. I have tried having the respons propper, as well as this way. I had to adjust the flow to remove the " around propertynames. Still same result.
This is how the table looks in collections:
This is how it looks when I am entering the data manually:
this is the direct output from :
{
"testoutput": "[{id:1,name:\"test\",lines:[{id:244,StrategyId:1,TypeId:0,fromWeight:10,toWeight:200}]},{id:2,name:\"tester\",lines:[{id:154,StrategyId:2,TypeId:0,fromWeight:10,toWeight:200}]}]"
}
The biggest difference is the escape characters added from flow.
This took me quite some time to solve so maybe will help others.
When you want to return an array (collection) form Flow to a Canvas App you need to use Response (Request), not Respond to PowerApps.
All the problems go away with that
Tip: Remember to provide a SCHEMA and to remove and re-add the flow in the canvas app
It looks like your Collecting a single column of Text from the API Response rather than collecting the entire response.
Try just using:
ClearCollect(colNewTable,'PowerApp->Sendmeamobilenotification'.Run())
If you want to set colNewTable as a variable, wrap it like:
Set(varNewTable,ClearCollect(colNewTable,'PowerApp->Sendmeamobilenotification'.Run())
Hope this helps!
I'm having trouble working out how to write a bit of XQuery. I have a JSON structure in MarkLogic that looks like:
{
"id": "pres003A10",
"title": "A Course About Something",
"description": "This course teaches people about some things they may not know.",
"author": "A.N. Author",
"updated": "2007-01-19",
"decks": [
{
"id":"really-basic-stuff",
"exclude": ["slide3", "slide12"]
},
{
"id":"cleverer-stuff",
"exclude": []
}
]
}
The exclude array contains the identifiers for slides in decks (presentations are made up of one or more decks of slides). I'm trying to write a piece of code that will look for a slide id in that exclude list and remove it if present or add it if not (a toggle).
I can obtain the array node itself using:
let $exclude := doc('/presentations/presentation.json')/object-node()/decks[id = 'markup-intro']/array-node('exclude')
but I can't for the life of me see how I then update that array to either remove an item or add it. The intention is call a function something like:
local:toggle-slide($presentation) as object-node()
{
(: xdmp:node-update(...) goes here :)
};
So, how do I update that array?
In memory JSON node trees (and XML trees, for that matter) are immutable.
The way to modify a tree is to construct a new tree, copying the nodes that haven't changed and creating the parent node and ancestor node with the changes.
That said, there's an easier way to modify JSON. If you call xdmp:from-json() on the root node, you will get a mutable in-memory map / array structure.
You can then navigate to the array using map:get() on the maps and [ITEM_NUMBER] on the arrays and delete or insert items FOR the appropriate json:array object.
When you're done, call xdmp:to-json() to turn the root map back into a node.
Hoping that helps,
If you need to update the json in the database, you can use xdmp:node-replace. The catch with node-replace is though, that you have to feed it with a named node. To do that, you need to wrap the array-node in an object-node, and then grab the array-node inside the object-node on the fly. Here a working example:
xquery version "1.0-ml";
(: insert test data :)
xdmp:document-insert("/presentations/presentation.json", xdmp:unquote('{
"id": "pres003A10",
"title": "A Course About Something",
"description": "This course teaches people about some things they may not know.",
"author": "A.N. Author",
"updated": "2007-01-19",
"decks": [
{
"id":"markup-intro",
"exclude": ["slide3", "slide12"]
},
{
"id":"cleverer-stuff",
"exclude": []
}
]
}'
))
;
(: node-replace array-node :)
let $exclude := doc('/presentations/presentation.json')/object-node()/decks[id = 'markup-intro']/array-node('exclude')
return xdmp:node-replace($exclude, object-node{
"exclude": array-node{ "other", "slides" }
}/node())
;
(: view if changed :)
doc('/presentations/presentation.json')
Note: consider looking at MarkLogic's Server-side JavaScript (SJS) support. Updating JSON might seem more natural that way, particularly if you need to make multiple changes in one go.
HTH!
I have truly searched and I have not found a decent example of using the serializer to get objects from a differently formatted JSON response. My reason for not changing the format of the JSON response is outlined here http://flask.pocoo.org/docs/security/#json-security.
I'm not very good with javascript yet so I had a hard time understanding the hooks in the serialize_json.js or maybe I should be using mapping (I just don't know). So here is an example of my JSON response for many objects:
{
"total_pages": 1,
"objects": [
{
"is_completed": true,
"id": 1,
"title": "I need to eat"
},
{
"is_completed": false,
"id": 2,
"title": "Hey does this work"
},
{
"is_completed": false,
"id": 3,
"title": "Go to sleep"
},
],
"num_results": 3,
"page": 1
}
When ember-data tries to use this I get the following error:
DEBUG: -------------------------------
DEBUG: Ember.VERSION : 1.0.0-rc.1
DEBUG: Handlebars.VERSION : 1.0.0-rc.3
DEBUG: jQuery.VERSION : 1.9.1
DEBUG: -------------------------------
Uncaught Error: assertion failed: Your server returned a hash with the key total_pages but you have no mapping for it
Which totally makes when you look at my code for the data store:
Todos.Store = DS.Store.extend({
revision: 12,
adapter: DS.RESTAdapter.create({
mappings: {objects: "Todos.Todo"},
namespace: 'api'
})
});
My question is how do I deal with total_pages, num_results and page? And by deal, I mean ignore so I can just map the objects array.
All root properties you return in your JSON result are mapped to a DS.Model in Ember Data. You should not return properties that are not modelled or you should model them.
If you want to get rid of the error you should make an empty model for the properties you don't use.
Read more here
Why are you returning properties you don't want to use? Or is it out of your control?
The way to accomplish this is with a custom serializer. If all your data is returned from the server in this format you could simply create ApplicationSerializer like this:
DS.RESTSerilizer.extend({
normalizePayload: function(type, payload) {
delete payload.total_pages;
delete payload.num_results;
delete payload.page;
return payload;
}
});
That should allow Ember Data to consume your API seamlessly.
Ember is fairly opinionated about how things are done. Ember data is no exception. The Ember team works towards certain standards that it thinks is best, which is, in my opinion, a good thing.
Check out this post on where ember is going. TL;DR because there are so many varying implementations of api calls, they're setting their efforts towards supporting the JSON API.
From my understanding, there is no easy way to do what you're asking. Your best bet is to write your own custom adapter and serialized. This shouldn't be too hard to do, and has been done before. I recommend you having a look at the Tastypie adapter used for Python's Django Tastypie
I need to retrieve JSON data and display using dojo datagrid. My JSON is like this
var data = {
"key":[{
"key1": "info1"},
{
"key2": "info2"},
{
"key3": "info3"}
]};
Thanks in advance
This is kinda difficult to answer, because its hard to tell what you have already tried..
I therefore assume, you already got the DataGrid to render (using a store, like Daniel Hu suggested) and now you want to "filter" for this specific Entry.
To do so, you migth have to fix the way you set up your store like that before:
var yourData = {
"key": [{
"key1": "info1"},
{
"key2": "info2"},
{
"key3": "info3"}
]
};
var yourStore = new dojo.data.ItemFileReadStore({
data: {
identifier: 'key1',
items: yourData.key
}
});
You can now filter the rows that will show up within the DataGrid using the query-property of the DataGrid like this:
var grid = new dojox.grid.Datagrid({
store: yourStore,
[some other properties, (especially the structure)],
query: {key1: 'info1'} // this is where you set you filter...
}, yourDomNode).startup();
Please note, that with the given example data, this would result in a grid with one row containing only one cell showing "info1". The items-property of the store expects an array, containing object. Each of those object should represent one row, so i guess you got this very concept wrong. What i mean is: key1 should normally be an object. So it might indeed be 'useful' to have a look at the link recomended by Daniel Hu..
As i already mentioned in my comment: if that doesn't answer your question, it might be useful if you post some code showing what you have already tried and which illustrates the unbeloved behaviour (if it already "behaves" in some kind of way...). Also tell exactly what result you expect and what actually comes out.
A dojo DataGrid requires a store. This should help you out:
http://dojotoolkit.org/documentation/tutorials/1.7/store_driven_grid/
I've been lurking on Stack Overflow for quite some time now, and have found quite a number of very helpful answers. Many thanks to the community! I hope to be able to contribute my own helpful answers before too long.
In the meantime, I have another issue I can't figure out. I am using Sencha Touch to create a Web-based phone app and I'm having trouble using a nested loop to iterate through some JSON. I can grab the first level of data, but not the items nested within that first level. There is a somewhat related ExtJS thread, but I decided to create my own since ExtJS and Touch diverge in subtle yet important ways. Anyway, here is some code to show where I am:
JSON (truncated - the JSON is PHP/MYSQL-generated, and there are currently actually three sub levels with "title", all of which I can access. It's the sub level "items" through which I can't iterate):
{
"lists": [
{
"title": "Groceries",
"id": "1",
"items": [
{
"text": "contact solution - COUPON",
"listId": "1",
"id": "4",
"leaf": "true"
},
{
"text": "Falafel (bulk)",
"listId": "1",
"id": "161",
"leaf": "true"
},
{
"text": "brita filters",
"listId": "1",
"id": "166",
"leaf": "true"
}
]
}
]
}
Store:
var storeItms = new Ext.data.Store({
model: 'Lists',
proxy: {
type: 'ajax',
method: 'post',
url : LIST_SRC,
extraParams: {action: 'gtLstItms'},
reader: {
type: 'json',
root: 'lists'
}
}
});
Working Loop:
storeItms.on('load', function(){
var lstArr = new Array();
storeItms.each(function(i) {
var title = i.data.title;
lstArr.push(i.data.title);
});
console.log(lstArr);
});
Non-working Nested Loop:
storeItms.on('load', function(){
var lstArr = new Array();
storeItms.each(function(i) {
var title = i.data.title;
var id = i.data.id;
title.items.each(function(l) {
lstArr.push(l.data.text);
});
});
console.log(lstArr);
});
The non-working nested loop gives me the error "Cannot call method 'each' of undefined", in reference to 'title.items.each...'
I suspect this is because I've not set title to be a key to set up a key:value pair, so it just sees a list of strings...but I'm kind of at a loss.
I should mention that the store is populated via two Models that have been associated with one another. I know that the Store can access everything because I am able to do nested iterating via an XTemplate.
Any help will be much appreciated and hopefully returned to the community in kind before too long!'
-Eric
Eric, why the loop?
If your models are associated in the same way that the JSON is nested, then you should just be able to set autoLoad:true on the store, sit back and enjoy.
Anyway, on the assumption that you are needing these arrays for some other unrelated reason, the problem is that you are trying .each on
i.data.title.items
Surely you should be iterating through
i.data.items
Also, if the object is a model, you can use .get() instead of the data object:
var title = i.get('title);
Using new sencha touch 2 framework, you can create associations within the models exactly the same way how your json is returned.
Check Sencha Touch 2 Model Document which tells you the various config options on Model.
You may refer to this example of ST2 Nested List .
Hope this helps.
"title" is not a enumerable object, its a string. To iterate a string you'll need to split it to convert it into an array.
Also, instead of using Ext.each try a simple for (var x in obj) {} or for (var xc in obj.prop) {} If that works then the ext.each method should work as well but if ext cannot iterate the object it will just quietly fail.