JavaScript / jQuery: Hide/show fields

With SharePoint we use a lot of lists and libraries to store and share information, we add and change this information with the help of forms. In most cases we create one form with all the information required for the content. Even if not all the information is required for all types of content or if it depends on a phase or status. With the help of jQuery and JavaScript we can create a more dynamic form that will hide/show fields based on selected values of fields. Make sure to disable the quick option, otherwise user will be able to edit the field outside of the provided solution.

SharePoint 2013/Online: Disable Quick edit

  1. Open the list or library settings
  2. Open the Advanced settings
  3. Set Quick Edit to No

SharePoint 2010: Disable Datasheet editing

  1. Open the list or library settings
  2. Open the Advanced settings
  3. Set Datasheet to No

JavaScript: New Form

  1. Open your favorite JavaScript Editor.
  2. Create a new JavaScript file called NewFormHideShow.js
  3. Add the following base code to the JavaScript file.

    $( document ).ready(function() {
       
    }
    );
  4. The first step is to hide the columns. Find the display names of the field that need to be hidden. Note that you need the name located in the HTML nobr tag.
  5. You can use a DOM explorer to find the correct names.
  6. For each field add the following code.
    $('nobr:contains("[Field Name]")').closest('tr').hide(); 
    
  7. In my example I hide two fields, Finalized Date and Finalized By. My example code for the document ready function is shown below.
    $(document).ready(function()
       {
          $('nobr:contains("Finalized Date")').closest('tr').hide(); 
          $('nobr:contains("Finalized By")').closest('tr').hide();
       });
    
  8. The second step is to make the function that hides or shows the fields depended on the selected value.
  9. Add the following code to the JavaScript.
    (function($){
       function showHideRegionLocation() 
       {
          var FeedbackMatchingValue = 'Final';
    
          var thisDiv = $("select[title='Status']"); 
          var mmFieldValue = thisDiv.find("option:selected").text();
    		
          $('nobr:contains("Finalized Date")').closest('tr').hide(); 
          $('nobr:contains("Finalized By")').closest('tr').hide();
    			
          if (mmFieldValue.indexOf(FeedbackMatchingValue) > -1) 
          {
             $('nobr:contains("Finalized Date")').closest('tr').show(); 
             $('nobr:contains("Finalized By")').closest('tr').show();
          } 					
       }
    
  10. Set the var FeedbackMatchingValue to the value which will show the hidden fields.
  11. Set the var thisDiv to the name of the Field that is used to show/hide the fields. Note that different types are just for different columns example Select or Input.
  12. Add the hide and Show codes. The code hides or show the table row (tr).
  13. Add the final function to the code. This part makes sure the functions runs when a users selects and/or reselects the option.
    $(document).ready(function() {
       $("select[id^='Status'").on('blur', showHideRegionLocation).on('change', showHideRegionLocation);
       });
    })(window.jQuery);
  14. Change the value after id^ to the field that contains the value on which field are being shown/hidden.
  15. The final code looks like this.
    $(document).ready(function()
       {
          $('nobr:contains("Finalized Date")').closest('tr').hide(); 
          $('nobr:contains("Finalized By")').closest('tr').hide();
    });
    
    (function($){
       function showHideRegionLocation() 
       {
       var FeedbackMatchingValue = 'Final';
       
       var thisDiv = $("select[title='Status']"); 
       var mmFieldValue = thisDiv.find("option:selected").text();
    		
       $('nobr:contains("Finalized Date")').closest('tr').hide(); 
       $('nobr:contains("Finalized By")').closest('tr').hide();
    			
       if (mmFieldValue.indexOf(FeedbackMatchingValue) > -1) 
       {
          $('nobr:contains("Finalized Date")').closest('tr').show(); 
          $('nobr:contains("Finalized By")').closest('tr').show();
       } 	
    }
    
    $(document).ready(function() {
       $("select[id^='Status'").on('blur', showHideRegionLocation).on('change', showHideRegionLocation);
       });	
    })(window.jQuery);
    

JavaScript: Edit Form

  1. The edit form is almost completely the same, only the last function is different.
  2. Open your favorite JavaScript Editor.
  3. Create a new JavaScript file called EditFormHideShow.js
  4. Follow the steps 3 – 12 from the chapter JavaScript: New Form.
  5. Add the final function to the code. This part makes sure the functions runs when a users selects and/or reselects the option.
    $(document).ready(function() {
       setTimeout(function() {
          showHideRegionLocation();
       }, 1000);
       $("select[id^='Status'").on('blur', showHideRegionLocation).on('change', showHideRegionLocation);
       });	
    })(window.jQuery);
    
  6. Change the value after id^ to the field that contains the value on which field are being shown/hidden.
  7. The final code looks like this.
    $(document).ready(function()
       {
          $('nobr:contains("Finalized Date")').closest('tr').hide(); 
          $('nobr:contains("Finalized By")').closest('tr').hide();
    });
    
    (function($){
       function showHideRegionLocation() 
       {
       var FeedbackMatchingValue = 'Final';
       
       var thisDiv = $("select[title='Status']"); 
       var mmFieldValue = thisDiv.find("option:selected").text();
    		
       $('nobr:contains("Finalized Date")').closest('tr').hide(); 
       $('nobr:contains("Finalized By")').closest('tr').hide();
    			
       if (mmFieldValue.indexOf(FeedbackMatchingValue) > -1) 
       {
          $('nobr:contains("Finalized Date")').closest('tr').show(); 
          $('nobr:contains("Finalized By")').closest('tr').show();
       } 	
    }
    $(document).ready(function() {
       setTimeout(function() {
          showHideRegionLocation();
       }, 1000);
       $("select[id^='Status'").on('blur', showHideRegionLocation).on('change', showHideRegionLocation);
       });	
    })(window.jQuery);

Adding JavaScript to a form

  1. Open the edit and/or new form of the list.
  2. Set the form in edit mode
  3. Add the Script Editor Web Part to the page
  4. Edit the SNIPPET and add the following code.

    <script src="../../SiteAssets/System/jquery-3.1.1.min.js" type="text/javascript"></script> 
    <script src="../../SiteAssets/System/EditFormHideShow.js" type="text/javascript"></script>
    
  5. Insert the code en Stop editing the form.
  6. Save the custom JavaScript HideColumns and the jQuery script in the correct location.
  7. The JavaScript will now run and hide or shows the field based on the selected value of the field Status.

 

JavaScript / jQuery: Set fields to read only

With SharePoint we use a lot of lists and libraries to store and share information. But not every bit of information needs to be managed/changed by users. Sometimes a workflow or code is responsible for the information. With default SharePoint it is not possible to set field to read only,  but with the help of jQuery and JavaScript we can. We can add JavaScript to the new and or edit form and disable (read only) any field we want. Make sure to disable the quick option, otherwise user will be able to edit the read only field using this feature.

SharePoint 2013/Online: Disable Quick edit

  1. Open the list or library settings
  2. Open the Advanced settings
  3. Set Quick Edit to No

SharePoint 2010: Disable Datasheet editing

  1. Open the list or library settings
  2. Open the Advanced settings
  3. Set Datasheet to No

Creating the JavaScript

  1. Open your favorite JavaScript Editor
  2. Create a new JavaScript file called HideColumns.js
  3. Add the following base code to the JavaScript file
    // A $( document ).ready() block.
    $( document ).ready(function() {
       
    }
    );
    
  4. Now you need to get the display names of the fields you need to set to read only (disable). Note that you need the correct name of the input, select, text area etc fields. Make sure you do not select the label of the field.
  5. You can use a DOM explorer to find the correct type of fields and the corresponding name. Note that different types are just for different columns
  6. In this example I selected the Multiple Lines of text field
  7. The selected code is
  8. In this code you are able to find the name: Multiple Lines
  9. And the type of field: textarea
  10. Do this for all the fields you need disable
  11. In my example I will disable the following fields
    Name Column Type Input field type
    Multiple Lines Multiple lines of text Textarea
    Title Single line of text Input
    Date Date and time Input
    Choice Choice Select
  12. Depended on the type of field different code is required.
  13. For Input and textarea use
    .attr("disabled", "disabled"); 
    
  14. For select we use
    .prop("disabled", true);
    
  15. The final code will look as follows
    // A $( document ).ready() block.
    $( document ).ready(function() {
        jQuery("input[title='Title']").attr("disabled", "disabled"); 
        jQuery("textarea[title='Multiple Lines']").attr("disabled", "disabled");
        jQuery("input[title='Date']").attr("disabled", "disabled"); 	
        jQuery("select[title='Choice']").prop("disabled", true);
        }
    );
    

Adding JavaScript to a form

  1. Open the edit (or new) form of the list.
  2. Set the edit form in edit mode
  3. Add the Script Editor Web Part to the page
  4. Edit the SNIPPET and add the following code

    <script src="../../SiteAssets/System/jquery-3.1.1.min.js" type="text/javascript"></script> 
    <script src="../../SiteAssets/System/HideColumns.js" type="text/javascript"></script> 
    
  5. Insert the code en Stop editing the form.
  6. Save the custom JavaScript HideColumns and the jQuery script in the correct location
  7. The JavaScript will now run and set the required field on read only when the edit form is opened

SharePoint 2010 Workflow: Capture document set versions

When a user changes a document set the version is not automatically capture, the user can capture the version by manually . Capturing a version manually is down with the Capture Version button located in the Document Set Tab in the ribbon. This is not the a secure way to make sure all versions are captured. With a SharePoint 2010 workflow (not workflow 2013) you can capture all the versions automatically. The solution has been tested on SharePoint 2013 On Premise and SharePoint Online (Office 365).

Solution

There is a small bug with the action Capture a version of the Document Set, the action runs multiple time (equal to the number of columns) and captures multiple versions. To prevent this from happening add a wait action to the workflow, this will make sure that only one version will be captured.

  1. Create a SharePoint 2010 workflow
  2. Configure the workflow to Start Workflow automatically when an item is Changed
  3. Add the action Wait for Field Change in Current Item
  4. Set the action to: Wait for Modified by (column) to equal Current Item: Modified By (column)
  5. Add the action Capture a version of the Document Set, with comment: Version Captured by Workflow.
  6. The full workflow looks like this

SharePoint: Get the Role ID

SharePoint uses role ID’s to create the permissions levels for SharePoint Groups. These role ID’s are a set of numbers that define the precise permissions level details.
The most used role ID are for Visitors (Read), Members (Contribute) and Owners (Full control). When you need other permission levels, creating the correct numbers can be difficult. With the help of the following steps it will be easy to create/find the role ID’s you need. This solution works for SharePoint Online and SharePoint 2013. The role ID’s are used when setting permissions using a rest call, see the blog post SharePoint 2013 Workflow: Changing Permissions with REST Calls for the details.

Permissions level  Role ID
Full Control 1073741829
Contribute 1073741827
Read 1073741826

Solution

  1. Open the SharePoint 2013 or Online site.
  2. Create the required Permission level on the Site Collection
  3. Go Site Settings – Site Permissions
  4. Open the Permission Levels
  5. Create a custom permission level, in this example I created a permission level called Custom Contribute.
  6. Now we need to find the corresponding role ID
  7. Create the following URL for your farm / site
    https://contoso.sharepoint.com/sites/dev/_api/web/roledefinitions
    
  8. This will open a page which looks like an RSS feed.
  9. Right click on the page to View Source, this will open the Source in Notepad.
  10. Now copy the code into your favorite XML editor.
  11. Search the XLM for the correct entry
  12. The Role ID is located in the link tag. The Role ID for my custom permission level is 1073741927
  13. The Role ID can now be used in web services, see the blog post SharePoint 2013 Workflow: Changing Permissions with REST Calls for the details.

SharePoint 2013 Workflow: Changing Permissions with REST Calls

SharePoint 2013 workflows do not have a default action to change item or list permissions. With the help of the call http web service action I was able to create multiple REST calls that can interact with the permission. In this blog post describes multiple workflows for specific interactions involving permissions. The solutions where build on SharePoint Online (Office 365) using SharePoint 2013 workflows.

Breaking the inheritance on current item

This workflow will break the inheritance of the item the workflow is running on. It is possible to change the regURL to break the inheritance of different items. If needed set the actions within an App step to make sure the workflow has the required permissions, see the blog post SharePoint 2013 Workflow: App step and App Permissions.

  1. Create a SharePoint 2013 workflow
  2. Create a dictionary variable called JSONRequestHeader
  3. Create a string variable called regURL
  4. Add the action Build Directory, select JSONRequestHeader as the variable
  5. Add Accept and content-type to the directory with the following code:
    application/json;odata=verbose
    

  6. Then store the following URL to the variable regURL

    [%Workflow Context:Current Site URL%]/_api/lists/getbytitle('[%Worklfow Context:List Name%]')/items([%CurrentItem:ID%])/breakroleinheritance(true)
    

  7. Add the Call HTTP web service action to the workflow and set the “this” to the regURL
  8. Set RequestHeaders to Variable: JSONRequestHeader
  9. Set RequestType to HTTP Post
  10. The full workflow looks like this

Set permissions on current item

This workflow will set permissions on the item the workflow is running on. It is possible to change the regURL to set permission on different items. If needed set the actions within an App step to make sure the workflow has the required permissions, see the blog post SharePoint 2013 Workflow: App step and App Permissions.

  1. Create a SharePoint 2013 workflow
  2. Create a dictionary variable called JSONRequestHeader
  3. Create a string variable called regURL
  4. Add the action Build dictionary, select JSONRequestHeader as the variable
  5. Add Accept and content-type to the directory with the following code:
    application/json;odata=verbose
    

  6. In this example we will grant the default members group contribute permissions.
  7. Add an step in the workflow called: Set Role Members
  8. Then store the following URL to the variable regURL
    [%Workflow Context:Current Site URL%]/_api/lists/getbytitle('[%Worklfow Context:List Name%]')/items([%CurrentItem:ID%])/roleassignments/addroleassignment(principalid='769',roleDefId=1073741826)
    
  9. The roleDefID sets the type off permissions
  10. The principalId is the ID of the permissions group, this is an unique id. You will need to find the principalId for your SharePoint Group, see the chapter Get SharePoint Groups principalId to learn how to find the principalId.
  11. Add the Call HTTP web service action to the workflow and set the “this” to the regURL
  12. Set RequestHeaders to Variable: JSONRequestHeader
  13. Set RequestType to HTTP Post
  14. The full workflow looks like this

Get SharePoint Groups principalId

  1. Open the SharePoint site where the SharePoint Groups are present
  2. Create the following URL
    [Current Site URL]/_api/lists/getbytitle('[List Name]')/items([Item ID])/roleassignments/
    
  3. In the source of the page you can find the principalId’s
  4. The principalId’s are located between the following tag
    <d:PrincipalId m:type="Edm.Int32">769</d:PrincipalId>

Remove all permissions on current item

This workflow will remove all permissions on the item the workflow is running on. It is possible to change the regURL to remove all permission on different items. If needed set the actions within an App step to make sure the workflow has the required permissions, see the blog post SharePoint 2013 Workflow: App step and App Permissions. With this workflow we will first break the inheritance, then get all permissions/roles on the item and then remove the roles. Only site collection administrator and farm admins will be able to access the item when the workflow has run.

  1. Create a SharePoint 2013 workflow
  2. Create a dictionary variable called JSONRequestHeader
  3. Create a dictionary variable called JSONDeleteHeader
  4. Create a dictionary variable called JSONResponse
  5. Create a dictionary called AllRoles
  6. Create a dictionary called RoleItem
  7. Create a string variable called regURL
  8. Create a integer called principalId
  9. Create a integer called Index
  10. Create a integer called countRoles
  11. Create a number called calc
  12. Add the action Build Dictionary, select JSONRequestHeader as the variable
  13. Add Accept and content-type to the directory with the following code:
    application/json;odata=verbose
    

  14. Add the action Build Dictionary, select JSONDeleteHeader as the variable
  15. Add X-HTTP-Method to the directory with the following code:
    DELETE
    

  16. The first step is to break the inheritance of the items, see above the chapter breaking the inheritance on current item for the steps.
  17. The second step is to get all SharePoint Groups (Roles) that have permissions on the item.
  18. Store the following URL to the variable regURL
    [%Workflow Context:Current Site URL%]/_api/lists/getbytitle('[%Worklfow Context:List Name%]')/items([%CurrentItem:ID%])/roleassignments
  19. Add the Call HTTP web service to the workflow and set the “this” to the regURL
  20. Set RequestHeaders to Variable: JSONRequestHeader
  21. Set RequestType to HTTP Post
  22. Set ResponseContent to JSONResults
  23. Add the action Get an Item from a Dictionary, select from Variable: JSONResults, with output to Variable:AllRoles and the following code
    d/results

  24. Then add the action Count Items in a Dictionary, select from Variable:AllRoles with output Variable: countRoles
  25. The third step is to remove all the Roles
  26. Add a loop that runs repeatedly while: Variable:Index is less then Variable:countRoles
  27. Add the action Get an Item from a Dictionary, select from Variable: JSONResults, with output to Variable:roleItems and the following code
    d/results([%Variable:Index%])
  28. Add the action Get an Item from a Dictionary, select from Variable: roleItem, with output to Variable:principalId and the following code
    PrincipalId

  29. Then store the following URL to the variable regURL
    [%Workflow Context:Current Site URL%]/_api/lists/getbytitle('[%Worklfow Context:List Name%]')/items([%CurrentItem:ID%])/roleassignments([%Variable:principalId%])
  30. Add the Call HTTP web service to the workflow and set the “this” to the regURL
  31. Set RequestHeaders to Variable: JSONDeletedHeader
  32. Set RequestType to HTTP Post
  33. Add the action Do Calculation select Variable:Index plus 1 and store the outcome in Variable: Calc
  34. Then Set Variable:Index to Variable:Calc
  35. The full workflow looks like this

SharePoint 2013 Workflow: App step and App Permissions

By default workflows run under the permissions of the user that starts the workflow, even is the workflow starts on a change or when a new item is created. The initiator does not always have the right permissions to complete all the actions within the workflow. For example when the workflow needs to delete an item, create a new items or use a web service. With SharePoint 2013 workflows it is possible to use the App step action to give the workflow its own permission set.

Solution part 1: Activate the feature

  1. The feature Workflows can use app permissions needs to be active.
  2. Open the site settings and click on Manage site features
  3. Activate the feature: Workflows can use app permissions

Solution part 2: Grant workflow app permissions

  1. Open the site settings and click on Site app permissions
  2. Copy the client section if the App Identifier. This is the identifier between the last “|” and the “@” sign, as shown in the figure.
  3. Navigate to the Grant permissions to an app page.This must be done by browsing to the appinv.aspx page of the site.
    http://}hostname}/{the Site Collection}/_layouts/15/appinv.aspx
    
  4. Fill in the App Id and click on Lookup
  5. The fields Title, App Domain and Redirect URL will be filled in automatically.
  6. Paste the following XML into the Permission Request XLM textbox to the grant the workflow App step full control
    <AppPermissionRequests>
        <AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="FullControl" />
    </AppPermissionRequests>
    
  7. Click on Create and on Trust It

Solution part 3: Using the App step

  1. Create a SharePoint 2013 Workflow with SharePoint Designer.
  2. Click on App Step in the ribbon to add the step.
  3. Add actions within the App Step and publish the workflow, for example: