Handling prerendered and server-side rendered forms in Vue.js
8 October 2018
We use different techniques to get the best user experience for our users. Two of them are prerendering (which we will call PR) and server-side rendering (which we will call SSR). The goal of these techniques is to give the user a first render before the main Vue component(s) is mounted.
Note: if you want to go straight to the final solution, you skip the problem and scroll to the end of the article.
The problem with forms
A form contains interactive elements, such as inputs and buttons. If you handle the form with Vue.js, and you use either PR or SSR, you can loose the values that user put in the prerender fields like this:
prerendered Vue.js form on a slow connection
I start typing and then I loose everything: focus, values, and so on. Let’s see why.
For our example, we will use:
- A single html file containing the prerendered form
- A Vue.js component containing the form that will be mounted on top of the prerendered form
Note: I have intentionally changed the prerender form title so we can see when the component is mounted. It is supposed to be the same with PR and SSR.
When the user visit your website, he first requests the HTML, which contains the prerendered form. The browser displays this form. Meanwhile, he downloads your javascript file, which contains your Vue component. During this time (download + execution of the javascript file), your user can enter values in the prerendered form.
When the javascript file is executed, your form component is mounted on top of the prerendered form. It literally replaces the DOM. The previous form is removed from the DOM, and so is the user inputs.
A smoother transition
What we want for our users is to have a transparent transition between the prerendered form and the new form.
We can use the Vue.js component hooks to solve this problem. When the hook created is triggered, you still have the prerendered form in the DOM, and you have access to your component data. This is when you want to retrieve the previous value and inject it in your component data.
Let’s see what it looks like:
Retrieve the user input values
Better. But we still loose the focus. To fix this, we are going to retrieve the user focus in the created hook, but we will only be able to put the focus on new input when the component is mounted, since the new input does not exist in the DOM when the created hook is triggered.
And here is the result:
Retrieve the user input values and the focus
Now the focus and the previous values are still there when the component is mounted.
The final solution is available, you can try it on a slow connection using chrome dev tools network tab.
Expert technique