We need to visualize graphs extracted from our Cuba application.
Is there any support for integrating graph visualization libraries (such as KeyLines, D3 etc)?
What is the best approach to do this?
Thank you!
We need to visualize graphs extracted from our Cuba application.
Is there any support for integrating graph visualization libraries (such as KeyLines, D3 etc)?
What is the best approach to do this?
Thank you!
Hi,
There you go:
Bye
Mario
I am aware of Cubaās Chart and Maps add-on.
My question is in regards to graph components, as in vertices and edges, graph traversals etcā¦
D3 and KeyLines are good examples.
I need to interface my Cuba application with graph processing libraries.
Hi!
You can add any JS library and wrap it by Vaadin component. See documentation how to do that.
Iāve created a simple project that uses D3.js. It sends JSON with data to the client side and builds a small diagram about the progress of tasks.
You should add all JS scripts that you need and CSS styles like in code below:
@JavaScript({"d3component-connector.js", "vaadin://d3.min.js"})
@StyleSheet("vaadin://diagram.css")
public class D3Component extends AbstractJavaScriptComponent {
Then in our JS connector we can use D3.js:
com_company_simpled3_web_toolkit_ui_d3component_D3Component = function() {
var connector = this;
var element = connector.getElement();
var dataJson = [];
connector.onStateChange = function(){
dataJson = JSON.parse(connector.getState().dataJson);
drawDiagram(element);
};
function drawDiagram(element) {
if (dataJson.length === 0) {
return;
}
d3.select(element).selectAll('div.item').data(dataJson).enter()
.append('div').attr('class', 'item')
.append('div').attr('class', 'data').append('span');
d3.select(element).selectAll('div.item').data(dataJson)
.select('div').style('width', function (d) { return (d.progress * 3) + 'px';})
.select('span').text(function(d){return d.progress;});
d3.select(element).selectAll('div.item').data(dataJson)
.append('div').attr('class', 'name')
.text(function (d) {return d.name;});
d3.select(element).selectAll('div.item').data(dataJson).exit().remove();
}
};
And finally we add our component to the layout. Task class is a POJO.
@Inject
private VBoxLayout vbox;
@Override
public void init(Map<String, Object> params) {
List<Task> tasks = Arrays.asList(
new Task("Task1", 14),
new Task("Task2", 26),
new Task("Task3", 82),
new Task("Task4", 57));
D3Component d3Component = new D3Component();
d3Component.setDataJson(new Gson().toJson(tasks));
Layout layout = vbox.unwrap(Layout.class);
layout.addComponent(d3Component);
}
And we get the following result:
Attached project: simple-d3.zip (158.0 KB)
Hi Pinyazhin,
I am trying to add a simple example with google table query js library similar to the process as mentioned in your comment.
I edited JS connector and added the JS script to the component class but I donāt see any results as expected. Do I have to make changes in the other files as well?
JS Connector:
com_company_simpled3_web_toolkit_ui_d3component_D3Component = function() {
var connector = this;
var element = connector.getElement();
var dataJson = [];
var dataSourceUrl = 'https://spreadsheets.google.com/tq?key=rh_6pF1K_XsruwVr_doofvw&pub=1';
var query, options, container;
connector.onStateChange = function(){
//dataJson = JSON.parse(connector.getState().dataJson);
//drawDiagram(element);
init();
};
function init() {
query = new google.visualization.Query(dataSourceUrl);
container = document.getElementById("table");
options = {'pageSize': 5};
sendAndDraw();
}
function sendAndDraw() {
query.abort();
var tableQueryWrapper = new TableQueryWrapper(query, container, options);
tableQueryWrapper.sendAndDraw();
}};
Regards,
Sanchit
HI!
Do you see exceptions in DevTools of your browser or in Tomcat logs? Make sure that you use all necessary js files.
I do see an exception:
SEVERE: Error sending state change eventscom.google.gwt.event.shared.UmbrellaException: Exception caught: (ReferenceError) : google is not defined
What do I have to add and where?
Thanks.
Regards,
Sanchit
It seems that the Google library is not imported. DId you add js files to the vaddin folder in web module? If it is possible could you attach a sample project where the problem is reproduced?
@Pinyazhin I did add the js files to the ui toolkit web module but do I have to add dependencies in the build.gradle web module?
sample.tar.gz (396.1 KB)
No, you shouldnāt add any dependencies to the build.gradle. Following the example in google docs you need to add loader.js to your OrgChartComponent
:
@JavaScript({
"vaadin://tablequerywrapper.js",
"https://www.gstatic.com/charts/loader.js",
"analytics-connector.js"
})
And you can load it from connector.onStateChange
:
connector.onStateChange = function(){
google.charts.load('current', {'packages' : ['table']});
google.charts.setOnLoadCallback(init);
};
I reworked your sample project with above code: orgchart.zip (42.9 KB)
@Pinyazhin It worked! Thank you.
I was just wondering If I can do the same by overriding a component action. for example, the chart should appear on a button click action.
It would be a great help if you could provide me an example.
Sanchit.
You can just add your component to the layout by click on a button:
<button id="showChartBtn" caption="Show chart" invoke="showChart"/>
@Inject
private ComponentsFactory factory;
public void showChart() {
MyComponent component = (MyComponent) factory.createComponent(MyComponent.class);
add(component);
}
Or for framework v7:
<button id="showBtn" caption="Show"/>
@Inject
private UiComponents uiComponents;
@Subscribe("showBtn")
private void onShowBtnClick(Button.ClickEvent event) {
MyComponent component = uiComponents.create(MyComponent.class);
getWindow().add(component);
}
@Pinyazhin I have a really annoying error when I just define a variable in the JS connector from Google API.
var formatter = new google.visualization.NumberFormat({prefix: ā$ā, negativeColor: āredā, negativeParens: true});
Exception Trace:
com.vaadin.client.communication.MessageHandler
SEVERE: Error sending state change eventscom.google.gwt.event.shared.UmbrellaException: Exception caught: (TypeError) : Cannot read property 'NumberFormat' of undefined
at Unknown.Ig(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.Mg(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.Sg(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.ry(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.new uy(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.Rx(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.VOb(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.hPb(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.AUc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.uUc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.JUc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.IGc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown._Hc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.cIc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.$Mc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.mNc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.eval(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.qi(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.ti(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.eval(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
Caused by: com.google.gwt.core.client.JavaScriptException: (TypeError) : Cannot read property 'NumberFormat' of undefined
at Unknown.Zqb(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.$x(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.Rx(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.VOb(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.hPb(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.AUc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.uUc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.JUc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.IGc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown._Hc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.cIc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.$Mc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.mNc(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.eval(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.qi(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.ti(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
at Unknown.eval(com.haulmont.cuba.web.toolkit.ui.WidgetSet-0.js)
Could you please check what is causing this issue.
This is concerning the library you use. You can check Google documentation in order to know which dependency you need to add for:
google.visualization.NumberFormat
Hi,
i am trying to use the simple-d3 project provided here. I am using cuba platform version 7.2.5. As the program do not run in this platform and as AbstractWindow is shown deprecated. I have made few changes as follows;
public void init(Map<String, Object> params)
have used regular public void onInit(InitEvent event)
function.I am getting an error that āno init function is defined and define one of following giving four optionsā though com_company_trial3d1_web_toolkit_ui_d3component_D3Component
is already defined in js file. Though rest of the code and files are same as provided in your project.
Please guide. Thanks
Hi,
possibly the previous version of your js connector is cached in the browser. You can try to open your app in private / incognito mode to check. Also, the connector function name:
com_company_trial3d1_web_toolkit_ui_d3component_D3Component
should be the same as FQN of D3Component
class:
com.company.trial3d1.web.toolkit.ui.d3component.D3Component
Thanks Roman for your reply,
I have tried as suggested by you but the error persists. I am attaching the project. Please have a look & guide.
Thanks
trial3d1.zip (604.1 KB)
Take a look at D3Component
class. In @JavaScript you have:
d3component-connector.js
but it should be:
D3Component-connector.js
Also, in D3Component-connector.js
replace: getJson
with dataJson
. It should be like this:
dataJson = JSON.parse(connector.getState().dataJson);
Because component state does not have getJson
field. If task names are misaligned, try to replace position: fixed;
with position: absolute;
in ā.nameā selector.
Thanks Roman,
@Javascript connector Name has solved the problem.
Thanks again.