Hi,
I am trying to integrate a javascript Spreadsheet component with CUBA and I’m experiencing the following difficulty. In the client side of the component, I define a custom spreadsheet formula which receives some arguments and calls a method from the middleware to process the data.
this.addCustomFormula("SUM", function (args) {
var excelObj = $('#Spreadsheet').data("ejSpreadsheet"),
argument = excelObj.getValueFromFormulaArg(args);
connector.netChange(argument); //<-- Middleware method
var state = connector.getState();
var data = state.data.result;
return data;
});
The method that is called in the middleware is the following one:
My intention in the client side method is to send the arguments in the middleware, get the calculated value synchronously and return this new value back to the spreadsheet. The problem has to do with the fact that the communication model between client & server components is asynchronous so I cannot get directly the new value from the State object. The new value is available through onStateChange() function but in my case this is not very useful since I need the new value before my javascript method returns. Is there any workaround for this kind of situations?
Hi Daniil,
Thank you for your reply. I just wish to ask you if there is any available sample either from cuba-platform or any add-on in the github that I could you as a starting point.
JavaScriptComponent has the following features which can serve your needs:
Register a function that can be called from the JavaScript using the provided name.
Invoke a named function that the connector JavaScript has added to the JavaScript connector wrapper object.
Putting these together, we can have the following:
Controller
// Register a function that will be called from the client-side.
jsComponent.addFunction("valueChanged", callbackEvent -> {
JsonArray arguments = callbackEvent.getArguments();
String text = arguments.getString(0);
// Send back the updated value
jsComponent.callFunction("updateValue", text.toUpperCase());
});
JS Connector
com_company_demo_JsDemo = function () {
var connector = this;
var element = connector.getElement();
element.innerHTML =
"<div class='caption'>Hello, world!</div>" +
"<div class='textinput'>Enter a value: " +
"<input type='text' name='value'/>" +
"<button name='btn'>Click</button>" +
"</div>";
var input = element.getElementsByTagName("input")[0];
// Update the value from the server-side
connector.updateValue = function (text) {
input.value = text;
};
var button = element.getElementsByTagName("button")[0];
// Send the value to the server-side
button.onclick = function () {
connector.valueChanged(input.value);
};
};
Hi Gleb,
Thank you very much for your prompt reply - it is really very interesting this approach but I think that there is a detail in my approach that requires a different approach. As you will notice in the javascript component (SpreadSheet), a javascript function is called from the spreadsheet and passes the arguments to a middleware method. The middleware method should process the data and returns back synchronously the result - this result is finally sent back from the javascript method to the component in order for an appropriate cell to get updated. At the provided example, I see that there are two separate steps involving two different actions - calling first a middleware method that it will call in turn another function. So, I was thinking of using a REST method call or RPC calls - I’ve checked the provided link from Daanil but I am not quite sure about how to use this mechanism correctly in the Cuba application.
This is impossible in modern web browsers. Synchronous AJAX calls are deprecated and are not recommended to use in web applications since they freeze the entire browser tab.
Hello, I am having an issue using the controller / connector setup you posted. I downloaded your js-demo to test what I was doing wrong in comparison to my current project. Your file worked without issues, until I renamed the function name in both the XML and the JS files. When I ran it, it gave me an error:
“Could not initialize JavaScriptConnector because no JavaScript function was found. Make sure one of these functions are defined:
com_company_demo_JsDemo_edited”
I found it odd that it didn’t work considering I changed the name of the function, so I changed it back to it original name and it gave me the same error
“Could not initialize JavaScriptConnector because no JavaScript function was found. Make sure one of these functions are defined:
com_company_demo_JsDemo”