ogobrecht / d3-force-apex-plugin

Oracle APEX Region Type Plugin: D3 Force Network Chart

Home Page:https://ogobrecht.github.io/d3-force-apex-plugin

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can you set node or link properties directly?

Ignacius68 opened this issue · comments

I have an app I'm working on in APEX that is a software registry. I express the interrelationships between code implementations as the graph of the operations of the code.

I worked out a segmentation strategy where I can pick one node and get all the direct dependencies of that node in a smaller graph. What I would like to do, then, is to set the "selected" property for the node that was originally selected, so the "center" of the dependencies is marked.

Is this possible? I haven't found a way yet, but I may be missing it.

Hi Ignacius68,

there is unfortunately currently no function to modify a node or link directly. But you can reuse the inspect function which returns the whole graph object. Here an example:

example.inspect().main.nodes.filter(function (node) {
  return node.ID === "7839";
}).style("fill", "blue");

example.inspect().main.nodes.filter(function (node) {
  return node.ID === "7839";
}).classed("myOwnClass", true);

Hope you get an idea. The filter, style and classed functions are D3 functions on an array of D3 objects - in this case the nodes. You can consult the D3 docs for more informations and examples.

The same would be possible with the links:

example.inspect().main.links.filter(function (link) {
  return link.TOID === "7839";
}).style("stroke", "red");

I tested on my own docs here: https://ogobrecht.github.io/d3-force-apex-plugin/tutorial-1-getting-started.html

Pleas note that the name of the graph in an APEX environment is something like d3_force_XXX. For example in the demo app under https://apex.oracle.com/pls/apex/f?p=18290:1 you can use this:

d3_force_emp.inspect().main.nodes.filter(function (node) {
  return node.ID === "7839";
})
.classed("selected", true)
.style("fill", "red");

Please align the code to your needs.

Hope I could help you. I created a note for me to implement two functions with direct access to the nodes and links for a future version.

Best regards
Ottmar

Ottmar! You're a god! :)

Not only did I get your script working in a couple minutes, it's a LOT better than my attempt.

In Global Declarations for the page:

function findID(item) { 
    return item.ID === jQuery('#P1_NODE_ID').val();
}

Node Click Function (where I experimented to get it working):

function(event, data) {
    newData = d3_force_Graph.data();
    index = newData.data.nodes.findIndex(findID);
    newData.data.nodes[index].selected = true;
    d3_force_Graph.start(newData);
}

Not only is this a nuclear approach, shuffling all the data around, it didn't result in the targeted node becoming selected state (e.g. as it would after a Lasso). While I was able to see the data, and watch it change in browser dev tools, it never applied that selected style to the node. I was sad.

I just need to find the right place to put the code now. I don't want it to run too early, but I can't find an event like "Force End" or something to attach to in APEX. I'd appreciate any ideas in this regard. For now, I just have it on a button.

This tool you've created here is just wonderful. I've been looking for something like this for a while, so I could work on a graph-data system like this. My strengths are data/backend development and architecture, frontend is NOT something I call myself good at. Thank you, thank you!

I just need to find the right place to put the code now. I don't want it to run too early, but I can't find an event like "Force End" or something to attach to in APEX. I'd appreciate any ideas in this regard. For now, I just have it on a button.

Wanted to pull that bit out separate. Can you suggest an event to use where this change would take effect? I was looking for "Force End" or something event like it, but don't see one. I've just started looking for a way to do this through the D3 API's.

It would seem to be a nice thing, however, to have "Force End" as an event to tie Dynamic Actions to, as a for instance.

Hi Ignacius,

No, I am not a god ;-) But thank you for your nice words. Such type of comments help me to stay motivated :-)

I plan to work next weekend on some of my open source projects. Hope to get a new version of the D3 plugin out then with new events. Need also to have a look at some other projects. You will hear from me...

Best regards
Ottmar

Hi Ignacius,

the new plug-in version v2.2.0 is out. I would recommend that you use the new event Render End in a Dynamic Action together with the new nodes method instead of the earlier mentioned inspect method. For details please see the API docs - you can simply follow the links in the release notes...

Hope you get your graph running like you want it. If everything is ok for you please close the issue.

Best regards
Ottmar

Hi Ottmar!

Your updates have let me do several things I was working on, including the on-page-load application of a saved set of positions and settings ("views" of the graph).

I got everything working nearly 100%, but I'm having an intermittent glitch where the "views" try to load but the Render End appears to have not finished yet. I think it's due to the sample data, which means there's 2 Render End events, one for the sample data, one for the loaded data.

Can the sample data be disabled? I can implement a counter on this, but it would be nicer to just turn off the sample data.

Regardless, I can close this, as your changes worked!

Hi Ignacius,

this seems to be bug - I have opened a issue (#32). The sample data should only be rendered when no data is delivered on the first render cycle. In your case a query is defined and there is no reason to render sample data.

You will hear from me when I have a solution for it.

Best regards
Ottmar

Thanks Ottmar! I have temporarily compensated for it with a counter that fires on iteration 2. :)