Input for Uploading Files in Web Component

To upload files through lightning web component, we can use one of two options:

  1. A dedicated component for files - lightning-file-upload.
  2. A lightning input with type: file.


The primary distinction is that the first is simpler to use and saves lines of code. Because the component already manages the uploading, error handling, and linking to the record.

However, the second option provides the developer with significantly more flexibility and is valuable in situations where the first option is insufficient. For example, if we want to do something else with the file, such as sending it by email or extracting data from it, or if we want to change the styling of the component.

In fact, it's the same trade-off as in many cases: use something that was already built but has limitation, or to invest more and develop something unique.


Another important consideration is the limitation related to file size and number of files that can be used. The maximum file size for the lightning-file-uploader is 2GB, which is sufficient for most cases. The lightning-input has no size limitation, but there are other considerations that might require attention (like payload size and heap size) depending on what we are doing with the file. Eventually with this option when we will need to process large files we need to use special logic in the code. For example, split the file to chunks.


Examples

We can use the following code to upload files in the first option. There is no need for Javascript code to process anything because the component already handles everything!


<template>
    <lightning-file-upload
        label="Attach File"
        name="fileUploader"
        record-id={recordId}
        multiple>
    </lightning-file-upload>    
</template>






As previously said, the component simplifies the procedure while allowing for some flexibility. Yes, we can limit the file types that can be used and provide a function that will be invoked after the component has finished uploading the file, however in many circumstances, this is insufficient.
In such cases, we should choose the second choice.


We can change our html code to the following. 

<template>
    <lightning-input
        label="Attach File"
        type="file"
        onchange={importFileChange}>

    </lightning-input>
</template>


Initially the UI for choose (or dragging) files will look exactly the same, however here we need to handle the processing ourself using the method onchange that calling javascript method. 

The example below demonstrates how to extract the file name and data, which is similar code for most use cases, then there should be unique code that process the file per the requirements. 

import { LightningElement, track, api } from 'lwc';

export default class FileUploaderDemo extends LightningElement {
    @api recordId;

    @track importFileName;
    @track importFile;


    importFileChange(event){
        const file = event.target.files[0];
       
        var reader = new FileReader()
        reader.onload = () => {
            this.importFile = reader.result.split(',')[1];
            this.importFileName = file.name;

            //Process the file data as needed
        }
        reader.readAsDataURL(file);
    }

}


We can send the file data to a server method for further processing, add custom validation for it and much more, we can also change its styling.

<template>
    <lightning-input
        label="Attach File"
        type="file"
        onchange={importFileChange}
        style="background-color:green;">
       
    </lightning-input>
</template>



Summary

The obvious choice is to use less code that should be as simple as possible, thus we'll want to utilize lighting-file-uploader as often as feasible, but the second option will be handy in the other circumstances. The idea is to use it only when truly unique functionality is required, rather than for easy applications such as improving the UI. 
Finally, keep in mind that writing code for uploading files can be  complex task that requires costly maintenance. As a result, it is advised to think carefully before choosing this way.


















Manage Profile Field Permissions with Apex

 



Recently, I encountered several cases where I needed to update profile permissions for fields in bulk. I was a bit disappointed to find that there are few free tools for such a task, and most of the ones I tested suffered from limitations of one kind or another. 

Because this is a recurring issue and also out of a desire to learn, I decided to try writing such a tool.

While exploring the options, I discovered that this can be done directly through Apex code. The permissions for the fields are stored in an object called FieldPermissions and users with setup permission can perform operations on the object.


The requirement was straightforward:

  • Option for selecting profiles and permissions.
  • Option for selecting a set of fields, including fields from different objects.
  • Checkboxes to modify the selected fields permissions for the profiles.
  • A save button, which will update the changes.


So I wrote a component (lwc) embedded in the Lightning Page that allows multiple selection of profiles or permission sets as well as multiple fields, editing and saving.

I would have liked to write that it is a simple process, but not this time. Managing permission is usually not an easy process.

Although it is about managing records in one object, there are special cases that require special attention. For example, you must not give write permission on a field formula, some standard fields that cannot receive permissions, and probably a few more that I haven't discovered yet.


I didn't publish the code for this process yet, as it is unstable, but I can share a few guidelines for anyone dealing with similar tasks:


  • Obviously, you cannot grant edit access to a field without also granting read access.
  • There are standard fields that cannot have permissions, for example, Id and CreatedBy. In most cases, we can identify those using the method isPermissionable from DescribeFieldResult
System.debug('Account.Rating isPermissionable: ' + Schema.getGlobalDescribe().get('Account').getDescribe().fields.getMap().get('Rating').getDescribe().isPermissionable());
System.debug('Account.Id isPermissionable: ' + Schema.getGlobalDescribe().get('Account').getDescribe().fields.getMap().get('Id').getDescribe().isPermissionable());

//01:44:58:103 USER_DEBUG [1]|DEBUG|Account.Rating isPermissionable: true
//01:44:58:123 USER_DEBUG [2]|DEBUG|Account.Id isPermissionable: false

  • There are other cases that the method isPermissionable doesn't cover; for example, you cannot provide permission for different sections of an Address field (e.g. BillingCity, BillingCountry), even though those fields are available in the object. Should give access only to the main field (BillingAddress).
  • Cannot provide edit access for formula fields.
  • Removing access for a field can be done either by deleting the FieldPermissions record or by setting Edit/Read both to false. In such a case, Salesforce will automatically delete it. It also means that when querying the existing permissions for fields with no access, you won't find a FieldPermissions record.
  • For my requirement, I added permissions only for fields, but a similar process can be done for object permissions and Apex/Pages permissions using the standard objects ObjectPermissions and SetupEntityAccess, respectively.
  • Cannot grant access for manage permission set (should be obvious)


Summary 

After dealing with such a process and understanding some of the difficulties involved, I can see why there are few such free quality tools. In my opinion, if you encounter such a need for mass update field permissions, the first recommendation is to try to use the existing tools. Either the Salesforce standard, even if sometimes it takes more time, or external tools.

Another option is to write a one-time script that will update/create relevant FieldPermissions records. 

List<FieldPermissions> newFieldsPermission = new List<FieldPermissions>();

newFieldsPermission.add(new FieldPermissions(
	PermissionsRead = true,
	PermissionsEdit = true,
	ParentId = 'ProfileOrPermssionSetId',
	SobjectType = 'Account',
	Field = 'Accunt.Rating')));

insert newFieldsPermission;


It is also possible to construct the relevant data in a csv and then import it to Salesforce as any other data. 






Retire of Permission on Profiles

If you are working as a Salesforce admin/developer you've probably heard somewhere that Salesforce is planning to make a significant cha...