Changes in a portion of the state for Vaadin's AbstractJavascriptComponent

I am currently working on implementing a JavaScript-based component for Vaadin that will be responsible for displaying and updating a large data set. To achieve this, I am extending AbstractJavaScriptComponent.

My goal is to keep the JavaScript side as simplistic as possible by delegating user interactions to the server through RPC calls, which then updates the shared state. Subsequently, the onStateChange function of the JS connector wrapper is triggered with the updated state, leading to the necessary DOM updates.

However, I have encountered two main challenges:

  1. I do not want to transfer the entire data set each time a small portion is modified.
  2. I aim to avoid completely rebuilding the UI every time an update occurs.

To address the second issue, I am keeping track of the previous state and comparing it to identify changes, allowing me to make targeted DOM updates when needed. However, the first problem still persists.

Should I abandon Vaadin's shared state mechanism in favor of exclusively using RPC for relaying state changes?

Update: After some testing, it seems that Vaadin's shared state approach lacks efficiency:

Whenever the component invokes getState() to update a property within the state object (even without making any actual changes), the entire state object is transmitted. As far as I can tell, the only way to circumvent this is to forego the shared state method and opt for RPC calls to communicate specific state alterations to the client.

The RPC strategy poses its own challenges that must be addressed; for instance, if you modify a value multiple times within one request/response cycle, sending multiple RPC calls is not ideal. Instead, only the final value should be transmitted akin to how the shared state mechanism responds with only the end state. One possible solution is to maintain dirty flags for individual state components or store a copy of the previous state for comparison. Nonetheless, triggering the RPC call at the culmination of request handling remains a concern. How can this be achieved?

Any insights or suggestions on this matter are greatly appreciated!

Update 2:

Vaadin 8 resolves the fundamental issue by transmitting only the altered state properties. Additionally, it no longer triggers onStateChange() on the JS connector when solely executing an RPC call (without modifying any state).

Answer №1

It has been noted that shared state synchronisation can be inefficient for components based on AbstractJavaScriptComponent. The entire state object is serialized and provided to the Javascript connector's onStateChange method whenever the connector is considered dirty. In contrast, other non-javascript components handle state updates more efficiently by only sending changes rather than the entire state object. This difference in handling of state updates can be observed at line 97 in

com.vaadin.server.LegacyCommunicationManager.java

boolean supportsDiffState = !JavaScriptConnectorState.class
            .isAssignableFrom(stateType);

The reason behind this divergence in state update handling for AbstractJavaScriptComponent-based components is not clear. Perhaps it aims to simplify the javascript connector process and eliminate the necessity of constructing a complete state object from deltas. It would be beneficial if this aspect could be addressed in upcoming versions.

One possible solution is to eliminate JavaScriptComponentState entirely and depend on server-to-client RPC for updates. Maintaining dirty flags within your server-side component or comparing old state with new state using any preferred method are feasible approaches.

To consolidate changes and transmit only one RPC call per modification, you can override

beforeClientResponse(boolean initial)
within your server-side component. This method is executed just before transmitting a response to the client, providing an opportunity to incorporate a series of RPC calls to update the client-side component.

Alternatively, overriding encodeState allows you the flexibility to send any desired JSON data to the client. You have the liberty to append a list of alterations to the base JSON object retrieved from super.encodeState, which can then be interpreted accordingly by your javascript connector's onStateChange method.

An additional tip: invoking getState() in your server-side component will mark the connector as dirty. To obtain state without triggering the dirty flag, utilize getState(false) instead.

Answer №2

After our recent conversation regarding this matter, I have devised a drop-in replacement for the AbstractJavaScriptComponent that sends state changes incrementally and incorporates some additional features. While still in its early stages of development, it shows promise.

Explore the repository here

The solution appears to be straightforward at first glance: essentially enabling differential state computation by circumventing a specific line of code within

com.vaadin.server.LegacyCommunicationManager.java
:

boolean supportsDiffState = !JavaScriptConnectorState.class
        .isAssignableFrom(stateType);

Implementing this solution proved to be complex due to the limited extensibility of Vaadin classes, resulting in the need to duplicate and re-implement 6 separate classes.

Answer №3

The functionality of Vaadin's shared state is designed to meet your needs seamlessly: upon the initial addition of a component to the DOM, the entire shared state is sent from server to client to enable display of the component. Subsequent updates only involve transferring changes. This means that when you modify a visible component's caption using

component.setCaption("new caption")
, Vaadin will transmit only the updated caption text to the client and integrate it into the existing client-side shared state for that component.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Leveraging Ajax for Executing a MySQL Query in PHP upon Clicking the Facebook Like Button

Is it possible to execute a MySQL query whenever a Facebook Like button is clicked on a webpage? I am aware that FB.Event.subscribe('edge.create', function(response) {} is used for such actions. However, my lack of knowledge in Javascript and AJA ...

What is the best way to determine the total number of rows that have been generated by the Asp:Repeater?

I'm looking for a way to retrieve the total number of rows generated by the repeater control using either Javascript or JQuery. Can anyone help me with this? ...

What is the best way to use a computed property as a style value for a component in Vue.js?

My component's template includes the following HTML element: .grid-item(:style="{ width: columnWidth, backgroundColor: 'blue' }") I want to dynamically set the width of this element using a computed property: computed: { columnWidth () ...

Steer clear of directly accessing views in AngularJS using angular-ui-router

In my AngularJS App setup, I have the following configuration: angular .module('MyApp') .config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function($stateProvider, $urlRouterProvi ...

Interact with Datatable by clicking on the table cell or any links within the cell

When I am working with the datatable, I want to be able to determine whether a click inside the table was made on a link or a cell. <td> Here is some text - <a href="mylink.html">mylink</a> </td> Here is how I initialize my da ...

Attempting to showcase the data stored within MongoDB documents on my website's user interface

I am facing difficulties in showing the data stored in my database on the front end of my grocery list app, which is built using the MERN stack. I have a form that successfully sends data to MongoDB and saves it upon submission. In order to retrieve the d ...

Can anyone provide a solution for determining the number of active intervals in Javascript?

Similar Question: How to View All Timeouts and Intervals in JavaScript? I've been working on an HTML5 game that includes a lot of graphical effects using intervals created by the setInterval function. However, I've noticed that my game is ru ...

What could be the reason for typescript not issuing a warning regarding the return type in this specific function?

For instance, there is an onClick event handler attached to a <div> element. The handler function is supposed to return a value of type React.MouseEventHandler<HTMLDivElement> | undefined. Surprisingly, even if I return a boolean value of fal ...

Tips for automatically filling out a div class form:

I currently have an Autoresponder email form featured on my webpage. Here is a snippet of the code for the section where customers enter their email: <div id = "af-form-45" class = "af-form" > <div id = "af-body-45" class = "af-body af-standa ...

Following a Node/Npm Update, Sails.js encounters difficulty locating the 'ini' module

While developing an application in Sails.js, I encountered an authentication issue while trying to create user accounts. Despite my efforts to debug the problem, updating Node and NPM only resulted in a different error. module.js:338 throw err; ...

Angular6 HttpClient: Unable to Inject Headers in Get Request for Chrome and IE11

Under my Angular 6 application, I am attempting to make a GET request while injecting some custom Headers: Here is how my service is structured: @Injectable() export class MyService { constructor(public httpClient: HttpClient) { } getUserInfos(login): Ob ...

What could be causing the Autocomplete feature to display as undefined?

I'm encountering an issue where the Autocomplete box displays "undefined" even though it returns the expected results. How can I resolve this problem? import { Drawer, List, Typography, Switch, ListItem, ListItemText, ListItemSecondaryAction, TextFiel ...

Is it possible to invoke the created() function in Vue from another method?

Currently, I am developing an application in Vue. Upon loading the page, a cookie containing the user's zip code is retrieved and used to perform a search. However, users should also have the ability to change their zip code if it is incorrect. I woul ...

Auto-fit HTML Webpage Resizer Simplified

Just finished my very first jQuery project, a simple full-width slider. I've been focusing on HTML & CSS and currently working with C#. The problem is that I don't want the page to be scrollable; I want it to autofit to the webpage. Imagine ope ...

Keeping extensive files/information on disk in order to alleviate browser memory usage in JavaScript

Currently, I am faced with a challenge involving the encryption of very large files. Unfortunately, my browser keeps crashing due to running out of memory while trying to handle these massive files. To address this issue, I am considering transferring som ...

Press `Enter` to confirm your selection in the BootstrapVue message box input box

Using Vue version v2.6.12 BootstrapVue version v2.21.2 Is there a way to confirm by pressing Enter instead of manually clicking OK? let text this.$bvModal.msgBoxConfirm(<input vModel={text} />) ...

What is the best way to dynamically update form fields in a database after making a selection in a <select> component?

Currently, I have a form that displays a list of stars (stellar objects) with a <select> control and two <inputs>. I am seeking guidance on how to populate the two inputs from the database when the user changes the selection in the <select&g ...

Express encountered an issue when trying to upload a file through AngularJS

I am currently facing an issue with uploading a file to express and subsequently to mongoDB. Despite my efforts, when I attempt to upload the file to express, it appears that no data is being passed through the response. I am utilizing ng-file-upload.min. ...

fullpage.js: the content exceeds the height limit

I am currently working on customizing the jquery script fullpage.js for a website built on the French CMS "SPIP" (). This script is used to create a one-page website with both horizontal and vertical navigation. However, I have encountered an issue with ...

Difficulty Loading Static JavaScript File in Express.js

Currently in the process of setting up an express server with create-react-app. Encountering this error in the console: Uncaught SyntaxError: Unexpected token < bundle.js:1 Upon clicking the error, it directs me to the homepage htm ...