Offline Pro : File Handling With Mobile & Salesforce : Create a file picker

AngularJS Jul 22, 2018

In this first post of my Offline Pro series, I will discuss creating a kind of File Picker with some advanced functionalities like:

  1. Using the device's camera to take pictures on the spot
  2. Pick multiple photos from photo library
  3. Pick random files from file explorer
  4. Show all selected images/files on a page like thumbnails.
  5. Preview them one by one to see them clearly.

To accomplish all of the above, we need :

  1. To add Camera plugin to your project to your config file
  2. Use of input[type='file'] element.

Camera Plugin - Prerequisite

To add the camera to your project using Ionic, run below commands

$ ionic cordova plugin add cordova-plugin-camera
$ npm install --save @ionic-native/camera

For any other framework, please use appropriate ways to add camera plugin. For this post purpose, I have added cordova-plugin-camera version 4.0.3

PS: Input file will not show camera option if camera plugin is not added to project. This is a prerequisite step if camera option is needed.

Use Input [type=file]

The purpose of using an input file is basically for two reasons:

  1. Gives an option to browse files in file explorer
  2. Allow selection of multiple files in a single go.

With Cordova camera plugin in markets, It is very difficult to find an appropriate plugin which allows multiple selections. This was my strong reason to use Input[type=file]

Step by step process of solution

Step 1: we should be able to select photos or take photos. For this, we need to handle onchange event on the input file. We can handle that in Angular by creating a directive and binding change event with a method like below:

//file directive to look for any change in the input file
//selection
(function() {
  'use strict';

  angular
    .module('starter.services')
    .directive("file",function(){
    return {
      scope: {
      // method that needs to be called once files are selected
        onFilesSelection: '&', 
      },
      link: function(scope,el){
        el.bind("change", function(e){
          var files = (e.srcElement || e.target).files;
          scope.onFilesSelection({files : files});
        }) 
      } 
    }
  })
})();

For any other JavaScript framework, just use onchange attribute on input file and fire a method to do same mentioned in above code.

Step 2: Now use above directive with input[type=file] to bind this change event

<input type="file" name="file" file on-files-selection="filePicker.onFilesSelection(files)" id="file-input" multiple="true"></input>

Step 3: With above input element, once files are selected, they will be passed to onFilesSelection method of the controller which will perform a reading of files/images binary data. This is possible with FileReader web API. By calling readAsDataURL, we can read the binary data of files and display them accordingly with provided base64 encoded string

Step 4: Put base64 encoded string in an array to show images on UI in thumbnails. The best way to display all files is to check the extension.

If files are images, use their base64 as it is in src attribute of img tag.

If files are non-images, replace src with pre-defined images for every extension like pdf, txt etc.

Step 5: Provide a fullscreen view to show full-screen images with some standard actions on thumbnails click.

Screenshots

PS: Screenshots are taken from IOS simulator which don't support camera. This is the reason Take a photo option is not coming. This works absolutely fine on device considering camera plugin prerequisite.

Full Code - FilePicker

Hope this will help to understand the core concepts of file handling stage 1 which is reading files.

As I said in my introduction post, Please try to do hands-on and see how far you can go & extend this solution to achieve point 2 in my introduction post i.e. Save images/files locally. You can also go to my introduction post from here.

Please do give your feedback if you like this post or want to improve something in solution. I will soon write another post for covering point 2 mentioned above.

Stay tuned!!