Limiting the number of uploaded files

From pmusers
Jump to: navigation, search

The MultipleFile control which is labeled as "uploadfile" in the DynaForm Designer does not have a property to limit the minimum and maximum number of uploaded files. The first programming example shows how to set a fixed minimum and maximum number of files that can uploaded in a MultipleFile control. The second example shows how to dynamically change the number of uploaded files and the allowed file types. The third example shows how to limit the number of files uploaded to a MultipleFile control inside a grid.

Setting a fixed minimum and maximum number of uploaded files

The following JavaScript example shows how to use the information stored in $("#multiple-file-id").getInfo().fileCollection to find out how many files were uploaded to a MultipleFile control when the Dynaform is submitted.


DynaForm: Set min and max uploaded files.json (right click and select Save link as)
Author: Amos Batto (amos@processmaker.com)
Version: 1.0 (2018-11-12)
Tested in: ProcessMaker 3.3 Community in Debian 9.5 with Firefox 52


Create a DynaForm which has a MultipleFile control with the ID "filesForCase":

MultipleFile-MaxAndMinFilesInDesigner.png

In this example, the MultipleFile control needs to have a minimum of 3 and a maximum of 4 uploaded files. When the form is submitted, the setOnSubmit() event handler will check how many files were uploaded to the form. If it doesn't find the right number of uploaded files, which are listed in the $("#multiple-file-id").getInfo().fileCollection.models[index] array, then the event handler will display an error message to the user and prevent the submission of the Dynaform by returning false.

Add the following JavaScript to the DynaForm:

var multiFileId = 'filesForCase';  //set to ID of MultipleFile field
var minFiles = 3;                  //set to minimum number of uploaded files
var maxFiles = 4;                  //set to maximum number of uploaded files

var formId = $("form").prop("id");

$("#"+formId).setOnSubmit( function() {
  var aFiles = $("#"+multiFileId).getInfo().fileCollection;
  var validFileCount = 0;
  
  for (i=0; i < aFiles.length; i++) {
    var filename = aFiles.models[i].attributes.file.name;
    
    if (!aFiles.models[i].attributes.isValid) {
      alert("Error: file "+filename+" is invalid. Delete it.");
      return false;
    }
     
    validFileCount++;
  }
  
  if (validFileCount < minFiles) {
    alert("Only "+validFileCount+" files were uploaded.\nA minimum of "+minFiles+" files are needed.");
    return false;
  } 
  if (validFileCount > maxFiles) {
    alert("The "+validFileCount+" files uploaded exceeds the maximum of "+maxFiles+" allowed files.\n"+
          "Please delete some files.");
    return false;
  }
})

The code loops through the fileCollection to count the files and check that that each file is valid (correctly uploaded and the right type) and displays an error message to the user if it isn't valid. Then it displays an alert() message to the user if the number of uploaded files is outside the minimum and maximum number of allowed files.

If too few files are uploaded, the following error message is displayed:

MultipleFile-TooFewFilesAlert.png

If too many files are uploaded, then the following error is displayed:

MultipleFile-TooManyFilesAlert.png

The form can only be submitted if the file count is between the minimum of 3 and the maximum of 4:

MultipleFile--AllowedToSubmit.png

Hiding the upload files button after uploading the correct number

The following example shows how to hide the correct number of files after the correct number of files has been uploaded.



DynaForm: Hide button to upload files.json (right click and select Save link as)
Author: Amos Batto <amos[at]processmaker.com>
Version: 1.0 (2019-05-07)
Tested in: ProcessMaker 3.3.4 Enterprise in Debian 9.5 with Firefox 60.5


In the following Dynaform, a maximum of 3 files should be uploaded to the "specFiles" MultipleFile field:

HideUploadFilesButton InDesigner.png

The following JavaScript will hide the button to upload more files once the correct number of files has been uploaded:

var multiFileId = 'specFiles'; //set to ID of the multipleFile field
var maxFiles = 3;              //set to the maximum number of files to upload
 
function hideFileButton() { 
  var aFiles = $("#"+multiFileId).getInfo().fileCollection;
  var validFileCount = 0;
  
  for (i=0; i < aFiles.length; i++) {
    if (aFiles.models[i].attributes.isValid) {
      validFileCount++;
    } 
  }
  
  if (validFileCount >= maxFiles) {
    $("#"+multiFileId).find("button").hide();
  }
  else {
    $("#"+multiFileId).find("button").show();
  }
}
    
setInterval(hideFileButton, 1000);

Set the multiFileId and maxFile variables in the above code.

Because the multipleFile.setOnchange() method doesn't work with MultipleFile fields, this code uses window.setInterval() to set a polling function that executes every second which checks whether that the correct number of files has been uploaded. If the correct number has been uploaded, then it hides the button to upload more button. If fewer files have been uploaded than needed, then it shows the button.

When this Dynaform is displayed while running a case, it will show the button to upload more files, as long as there are fewer than 3 files:

HideUploadButton lackingFiles.png

Once 3 files have been uploaded, the button will be hidden:

HideButtonAfterUploadingCorrectNumberOfFiles.png

If the user deletes a file from the list, then the button will be shown again, so another file can be uploaded.


Note: This method is not fool-proof, since the MultipleFile field allows the user to upload more than one file at a time, so more than 3 files could be uploaded. To prevent that too many files were uploaded, this code should be combined with the code in the previous section, which checks that the correct number of files were uploaded when the Dynaform is submitted.

Validating a variable number of uploaded files and the file type

This example shows how to force the user to upload a variable number of files selected by a field in the DynaForm. It also verifies that the file is one of the file types selected in a checkgroup in the same Dynaform.


DynaForm: Validate files in MultipleFile field.json (right click and select Save link as)
Author: Amos Batto (amos@processmaker.com)
Version: 1.0 (2018-11-12)
Tested in: ProcessMaker 3.3 Community in Debian 9.5 with Firefox 52


First, create the following DynaForm:

MultipleFile-ValidateFilesInDesigner.png

This form has the following fields:

  • Dropdown with the ID "numberOfFiles" to select the number of allowed files to be uploaded,
  • Checkgroup with the ID "typesOfFiles" to select the allowed file types, which are in the list of options:
    MultipleFile-FileTypesOptions.png
  • MultipleFile with the ID "filesForCase" to upload files for the case.

Then, add the following JavaScript to the DynaForm:

var multiFileId = 'filesForCase';
var formId = $("form").prop("id");


var multiFileId = 'filesForCase';
var formId = $("form").prop("id");

$("#"+formId).setOnSubmit( function() {
  var validFileCount = 0;
  var nRequiredFiles = parseInt( $("#numberOfFiles").getValue() );
  var aFileTypes = $("#typesOfFiles").getValue();
  var aFiles = $("#"+multiFileId).getInfo().fileCollection
  
  for (i=0; i < aFiles.length; i++) {
    var filename = aFiles.models[i].attributes.file.name;
    var ext = filename.match(/\.[a-z0-9]{0,8}$/);
    if (ext) {
      ext = ext[0];
    }
    
    if (ext === null || aFileTypes.indexOf(ext) == -1) {
      alert("Error: file "+filename+" doesn't have a permitted file type.\nDelete it and upload it again.");
      return false;   
    }
    
    if (!aFiles.models[i].attributes.isValid) {
      alert("Error: file "+filename+" is invalid. Delete it.");
      return false;
    }
        
    validFileCount++;
  }
  
  if (validFileCount != nRequiredFiles) {
    alert(nRequiredFiles+" files need to be uploaded. You have "+validFileCount+" files.")
    return false;
  } 
})

Like in the previous programming example, the number of files in the fileCollection is checked when the form is submitted. It checks the extension of the uploaded filename to determine the file type. A more reliable way to check the file type is to look at the file's MIME type which is stored at $("#multiple-file-id").getInfo().fileCollection.models[index].attributes.file.type, but this information is only available if the file was just uploaded in the current form.

If all the files in the MultipleFile control were just uploaded the following code can be used to verify the file type:

    var mimeType = aFiles.models[i].attributes.file.type;
    if (aFileTypes.indexOf(mimeType) == -1) { 
      alert("Error: file "+filename+" doesn't have a permitted file type.\nDelete it and upload it again.");
      return false;   
    }

Limiting the number of uploaded files inside a grid

Information about the files uploaded to a MultipleFile field inside a grid are stored in:

getFieldById(gridID).gridtable[rowNumber][columnNumber].getInfo().fileCollection.models[fileNumber].attributes

The counting of the rowNumber, columnNumber and fileNumber starts from 0 (zero).

For example, the following code gets the filename of the third uploaded file in the second row of a MultipleFile field which occupies the fifth column inside a grid whose ID is "clientsList":

var filename = getFieldById("clientsList").gridtable[1][4].getInfo().fileCollection.models[2].attributes.file.name;


The following is a longer example that shows how to use getFieldById("gridID").gridtable validate that a minimum and a maximum number of files have been uploaded to a MultipleFile field inside a grid.


DynaForm: Limit uploaded files inside grid.json (right click and select Save link as)
Author: Amos Batto (amos@processmaker.com)
Version: 1.0 (2019-04-02)
Tested in: ProcessMaker 3.3.6 Community in Debian 9.5 with Firefox 60


First, create the following DynaForm that has a grid to enter a list of products and upload files about each product:

LimitUploadsInsideGridInDesigner.png

The "productsList" grid has the following fields:

  • A text field with the ID "productName",
  • A MultipleFile field with the ID "productFiles"

Then, add the following JavaScript code to the Dynaform:

var gridId = 'productsList';  //set to ID of the grid holding the MultipleFile field
var fileColumnNo = 1;         //column number of MultipleFile field in grid, counting from 0   
var minFiles = 1;             //set to minimum number of uploaded files
var maxFiles = 2;             //set to maximum number of uploaded files

var formId = $("form").prop("id");

$("#"+formId).setOnSubmit( function() {
  var numRows = $("#"+gridId).getNumberRows();
  var gridTable = getFieldById(gridId).gridtable;

  for (var i = 0; i < numRows; i++) {
    var aFiles = gridTable[i][fileColumnNo].getInfo().fileCollection;
    var validFileCount = 0;
    
    for (var ii=0; ii < aFiles.length; ii++) {
     
      if (!aFiles.models[ii].attributes.isValid) {
        var filename = aFiles.models[ii].attributes.file.name;
        alert("Error: file "+filename+" is invalid. Delete it.");
        return false;
      }
      validFileCount++;
    }
    
    if (validFileCount < minFiles) {
        alert("Row "+(i+1)+" has "+validFileCount+" files, but a minimum of "+minFiles+" is required.");
        return false;
    }
    if (validFileCount > maxFiles) {
        alert("Row "+(i+1)+" has "+validFileCount+" files, but only "+maxFiles+" are allowed.");
        return false;
    }
  }
});

Set minFiles and maxFiles to the minimum and maximum number of files that allowed to be uploaded to each MultipleFile field in the grid.

When the user files out the following form and click on the submit button, the following error message will be displayed and the user won't be allowed to submit the Dynaform until the correct number of files is uploaded:

ErrorTooManyUploadedFilesInMultipleFileInGrid.png