We recently used Vue for the first time in a production setting and ran into a problem that we had not had to solve before: user uploaded files. On top of needing to store uploaded images, another requirement of the project was that it had to work in IE9. Simple enough requirements when taken individually, but more difficult together.
Our first thought was to try and leverage an existing Vue extension to handle the uploads. After struggling for a while with an external library that was built for a vastly different environment, we decided to roll our own solution. This ended up being a dead end too, with our main problem being setting the proper content headers across different file types and browser variations.
A few issues we had to solve:
- The name of the uploaded file is generated using other components of a larger form that the file uploader is attached to. Sometimes those elements have not been saved yet, so there is no way to access them within the scope of the FileUploader object to generate the proper filename.
- This particular page included multiple forms generated from a v-for loop, each one containing a FineUploader. We didn’t want to initialize these all at once for performance reasons, but just when we needed them.
- Inside an AJAX response your scope is limited to the response.
How we solved them
By default, FineUploader attempts to save the file immediately upon uploading. Luckily they make it extremely easy to defer the save until you trigger it manually through the API. That solved one issue quite simply. We just waited until the whole form was ready to save and initialized the uploader afterward.
We still did not have access to the scope of the Vue components within the instance of FineUploader. Thus, we couldn’t set the name of the file. This meant we would need to do that with FileUploader’s API before we could persist the file. As stated before, we needed other data from the Vue component to set the filename. The best place to do this is in the success callback of the API save of the question. However, within the AJAX response you do not have access to the FileUploader object either. The response is scoped to the Vue instance.
This was a sticking point for quite a while. Both issues meant that we didn’t have access to the data we needed in one way or the other. The solution proved to be simple (or, at least it seemed that way after much banging of the head against the desk).
First, upon the initialization of our Vue instance we created an empty object to serve as the mount point of FineUploader.
Next, we handled the initialization problem. The FineUploader instance was only instantiated by a click event within the larger form. This readied the FineUploader for action without the performance hit of instantiating instances not in use.
The initialization of the FineUploader did not happen until all the data for the form had loaded. This way we could scope the FineUploader instance to a specific form. This allowed us to store the variables we needed for the filename into FineUploader. Which went part of the way to solving problem 1.
The final bit of data we needed for the filename of the uploaded image is only available after the API response (the new ID for the created instance). The problem now was the lack of access to the Vue instance in the AJAX response.
no very few heads were damaging during the desk banging. Another win, win, win.
What's the JAMstack?
As a front-end developer in 2020, it is time that I fulfill the FEDeral mandate that I publish words regarding the JAMStack. If you follow too many developers on Twitter, it’s likely you’ve heard about the Next Big Thing in web development, but I’d like to put this trend (fad? movement?) into context to better understand what’s truly new about this approach and whether it’s worth using.Read More »
By:Mark Biek on 1/30/2018
ES6 generator functions make recursive asynchronous calls (relatively) easy.Read More »