X

Geertjan's Blog

Custom Component for Zipping and Downloading Files

Geertjan Wielenga
Product Manager

Here's a handy custom component (i.e., a CCA component) for zipping files and downloading them, in an Oracle JET application:

<fileDownloadForm
file="{{file}}"
content1="{{htmlContent}}"
content2="{{jsContent}}">
</fileDownloadForm>

I've created it as part of a project where we want to let developers design a CCA component and then download it as a ZIP file, so that it can be distributed to those who want to make use of the component. That's the reason you can see above that two files are assumed to be provided, with 'file' being the name of the file, used for both the view and the viewModel.

In an application, the above component is rendered as follows:

What happens when "demo" is changed to "sample" in the text field above and then the "Download" button is clicked? Well, when you do that, a download process begins and you'll have a ZIP file, with this content, yes!, a CCA component:

So... what this blog entry is about is... how to create a CCA component for downloading CCA components... 

The structure of the CCA component you'll create is as follows:

Here's the JSON file, "fileDownloadForm.json":

{
"properties": {
"file": {
"description": "file name.",
"type": "string"
},
"content1": {
"description": "html content.",
"type": "string"
},
"content2": {
"description": "js content.",
"type": "string"
}
}
}

Here's the view, in "fileDownloadForm.html":

<div class="oj-panel">
<label>ZIP Name:</label>
<input type="text"
data-bind="ojComponent: {
component: 'ojInputText',
value: file}"/>
<button class="oj-button-primary"
style="float: right;"
data-bind="
click: downloadFile,
ojComponent: {
component: 'ojButton',
label: 'Download' }">
</button>
</div>

Here's the business logic in the viewModel, "fileDownloadForm.js":

define(['knockout', 'jszip', 'file-saver'],
function (ko, JSZip) {
function model(context) {
var self = this;
self.file = null;
self.content1 = null;
self.content2 = null;
context.props.then(function (properties) {
if (properties.file) {
self.file = properties.file;
}
if (properties.content1) {
self.content1 = properties.content1;
}
if (properties.content2) {
self.content2 = properties.content2;
}
});
self.downloadFile = function (model, event) {
if (event.type === 'click' ||
(event.type === 'keypress'
&& event.keyCode === 13)) {
var zip = new JSZip();
zip.file(self.file+".html", self.content1);
zip.file(self.file+".js", self.content2);
zip.file("loader.js", "to be done");
zip.file("README.txt", "to be done");
zip.generateAsync({type: "blob"})
.then(function (content) {
saveAs(content, self.file+".zip");
});
}
};
}
return model;
}
);

The above assumes you've set up these two libraries in your application:

I.e., somehow, via Bower or otherwise, you've included them like this:

In 'main.js', you should have these references in the 'paths' of 'requirejs.config':

   'file-saver': 'libs/file-saver/FileSaver',
'jszip': 'libs/jszip/dist/jszip'

And, to wrap things up, tying everything together, you have "loader.js":

define(['ojs/ojcore',
'text!./fileDownloadForm.html',
'./fileDownloadForm',
'text!./fileDownloadForm.json',
'ojs/ojcomposite'],
function(oj, view, viewModel, metadata) {
oj.Composite.register('fileDownloadForm', {
view: {inline: view},
viewModel: {inline: viewModel},
metadata: {inline: JSON.parse(metadata)}
});
}
);

As a simple example of usage of the above, include the following in the "viewModel" of the handy custom component outlined at the start of this blog entry:

self.file=ko.observable('demo');
self.htmlContent=ko.observable('dummy html content');
self.jsContent=ko.observable('dummy javascript content');

Now, whenever you include the handy custom component, anywhere in your application, the user can click "Download" and then they'll have a ZIP file downloaded with the specified content in the specified files.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.