Quick SharePoint Approvals using list formatting JSON to set field values

This week it came to attention two new possible actions to buttons created using list formatting:

  • setValue: Updates a field value
  • openContextMenu: Displays the default context menu for the list item

With the first one, we can update the values of any field in the list item. And update multiple field values with a single click. 

Not only this but we can use dynamic values and do calculations using the JSON formatting formulas, for example, we could increment/decrement a number value by clicking a custom button created with JSON formatting. 

With that in mind, after seeing some samples on Twitter published by @techan_k, I thought this could be useful for approvals scenarios. For example, we can update the item status and who approved the item with a single click, so as in the example below:

The structure behind the example

Three list columns are needed:

  • A Choice column for the status (Suggested name: ‘Item Status’), with the possible values: Pending, Approved, Rejected. The standard configurable formatting for the Choice column can do the trick as below:
  • A user field to register who approved or rejected the item (Suggested name ‘Approval Action By’)
  • A dummy field to add the JSON template and display the buttons separately. The suggestion is to add a calculated field named ‘Approval‘.

The logic behind the sample

To make the functionality cleaner, the buttons would need to be displayed only when the items have not been approved. So we simply set the CSS display property to ‘none‘ when the status is not empty and is different than ‘Pending‘. And display a text message stating that the item was already approved or rejected.

On each button, we set as the customRowAction, an action using the new setField action, and pass two fields on each by using their internal names. Note that to set the current user as the value, we simply pass the @me formula.

Approval:

"customRowAction": {
              "action": "setValue",
              "actionInput": {
                "ItemStatus": "Approved",
                "ApprovalActionBy": "@me"
              }
}

Rejection:

"customRowAction": {
              "action": "setValue",
              "actionInput": {
                "ItemStatus": "Rejected",
                "ApprovalActionBy": "@me"
              }
}

Full sample

To add this to any SharePoint list, create the columns as stated above, and add the following JSON template to the Approval field (resize it to get the buttons to be displayed horizontally/vertically as you wish). Tweak the internal names as needed in case your list uses different field names:

{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/column-formatting.schema.json",
  "elmType": "div",
  "style": {
    "flex-directon": "row",
    "justify-content": "left",
    "align-items": "center",
    "flex-wrap": "nowrap"
  },
  "children": [
    {
      "elmType": "div",
      "style": {
        "display": "=if([$ItemStatus] == 'Pending' || [$ItemStatus] == '', 'inherit','none')",
        "flex-directon": "row",
        "justify-content": "left",
        "align-items": "center",
        "flex-wrap": "wrap"
      },
      "children": [
        {
          "elmType": "button",
          "customRowAction": {
            "action": "setValue",
            "actionInput": {
              "ItemStatus": "Approved",
              "ApprovalActionBy": "@me"
            }
          },
          "attributes": {
            "class": "ms-fontColor-themePrimary ms-fontColor-themeDarker--hover"
          },
          "style": {
            "border": "none",
            "background-color": "transparent",
            "cursor": "pointer",
            "display": "flex",
            "flex-directon": "row",
            "justify-content": "left",
            "align-items": "center",
            "flex-wrap": "wrap"
          },
          "children": [
            {
              "elmType": "span",
              "attributes": {
                "iconName": "SkypeCircleCheck"
              },
              "style": {
                "padding": "4px"
              }
            },
            {
              "elmType": "span",
              "txtContent": "Approve",
              "style": {
                "word-break": "keep-all"
              }
            }
          ]
        },
        {
          "elmType": "button",
          "customRowAction": {
            "action": "setValue",
            "actionInput": {
              "ItemStatus": "Rejected",
              "ApprovalActionBy": "@me"
            }
          },
          "attributes": {
            "class": "ms-fontColor-themePrimary ms-fontColor-themeDarker--hover"
          },
          "style": {
            "border": "none",
            "background-color": "transparent",
            "cursor": "pointer",
            "display": "flex",
            "flex-directon": "row",
            "justify-content": "left",
            "align-items": "center",
            "flex-wrap": "wrap"
          },
          "children": [
            {
              "elmType": "span",
              "attributes": {
                "iconName": "Blocked"
              },
              "style": {
                "padding": "4px"
              }
            },
            {
              "elmType": "span",
              "txtContent": "Reject",
              "style": {
                "word-break": "keep-all"
              }
            }
          ]
        }
      ]
    },
    {
      "elmType": "div",
      "children": [
        {
          "elmType": "span",
          "txtContent": "='This item is ' + toLowerCase([$ItemStatus])",
          "style": {
            "display": "=if([$ItemStatus] == 'Pending' ||[$ItemStatus] == '' , 'none','inherit')",
            "padding-left": "5px",
            "word-break": "keep-all"
          }
        }
      ]
    }
  ]
}

Conclusion

By using list formatting and the new setValue action, we can now update field values, expanding a lot the possibilities of what can be done in SharePoint/Microsoft Lists without the need of the SharePoint Framework field customizers or other techniques (calling a Flow for example). This example is just a simple one to show how to update two fields at the same time and use the native formulas as values, but the possibilities now have expanded massively.

Note: For this approach to work correctly, all fields used in the JSON template need to be added to the list view where the custom buttons will be added.

47 comments

  1. Great post!
    I’m tried and worked for me following your instructions. Now I’ll try to add the approval/denial date to the list.

    Thank you!

    1. I think so as it is on the official documentation. Also, I’ve just tried it on a tenant using Standard Release and it works fine. What error do you get?

  2. Hi Michel,

    I tried using your solution for a multiuser approval, also adding the possibility via a second button to delete the choice done by the user and return to Approve/reject status. The only issue I am finding is that using the operation “removeFrom” I am not able to remove the @me from the user array. Any thoughts?

    Thanks for this magnificent use case.

    Thank you,
    Davide

  3. Hi,
    When the item is “Rejected”, is it possible to show the comments field to put some description which is required field?. Please let me know this can be accomplish?

  4. Hi Michel,
    Please. help with issue below.
    After I click Approved or Rejected – only one fileld is changing: ApprovalActionBy.
    Other fields are not changing.
    Any suggestions?

      1. Hello,
        I am having the same problem.
        After I click Approved or Rejected – only one fileld is changing: ApprovalActionBy.
        Other fields are not changing.
        Any suggestions?

  5. Hi Michel,

    Thank you for the awesome post.

    I managed to make it in the list view. and also tried it a gallery view. However the buttons no longer work.

    Could you please advise? Thank you.

  6. What is the approval calculated off of? I am confused as I left the formula blank and SPO will not allow it be blank…Do I need to create an approval and rejection column…?

    1. It’s a dummy calculated column only to show the buttons (and not to be displayed in edit forms).
      You can add it with a simple formula as: = “APPROVAL”, just to be able to add it, and then it will be used only to render the buttons.

  7. Hello!
    Short question:
    Where do I have to insert your Code?
    In the Formula of the Column “Approval” or in the Column Formatting?
    This function would really help us in the project!

    Thank you!

    1. its working now! One more question: if I open the List in my app I can’t click on approved or rejected.
      Is there a way to implement the same function in the app?

      Thank you!!

    2. Hi Max, you have to add the code to the Column formatting, not to the formula…
      In the formula value you can add any dummy value as it will be hidden by the JSON formatting…

  8. Hello Nice Work!! Can we do something like this for content approval for submitted items? Like have a button to approve or reject the item? or to popup the form to approved or reject the item?

    Thank you in advanced

    1. Hi Obed, yes you can…This is sample is just to demonstrate the capability, but you can use different statuses…
      And also you can add a button to open the item in a Form…what do you need to do exactly?

  9. This has the potential to solve a huge problem for me! Buttons are available and my approved by column is populating correctly. However, I am unable to get the choices in the Item Status column to appear and when I select approve/reject, the text message does not populate. I think this may be because I have not set the customRowAction for Approve/Reject? Can you clarify where that code should be inserted?

    1. Hi Melissa, not sure if I understood your problem…You need to use the customRowAction, otherwise nothing will happen (field is not updated)…How did you use the JSON template exactly?

  10. Does it have to use a button? What if I wanted it to just update a column based on a value that already exists in another column? Thx

    1. Do you mean when you change a value in this column update another? If so you would need to use a custom form built with Power Apps or a Power Automate flow. The setValue option in list formating works when called from clicks on custom elements in the view/button formatter.

  11. How do you change an Items Status from Approved to Rejected or Back to Pending once the approval button has been already been selected. Example, I am the approver and after selecting Approved I realize that I need to reject instead and now I want to change the status to rejected. Thanks!

  12. This is an awesome topic and very applicable to a project that I am currently working on. I was able to recreate this and it works fine. I have 0-10 experience with JS or JSON. I am trying to add two more choice buttons “Initiate” and “Re-think” I dissected the code and added the two extra “children” in thee but they did not show up. I believe it’s something near the bottom of the code that I need to duplicate but can’t quite figure it out. Is this something you can assist me with? Also, I have never responded to one of these posts with issues because I am not sure what the proper etiquette of doing so entails.

    1. Hi Lance,

      Thank you for your feedback.

      You can send me your JSON content in the comments (good so more people see the responses) or as a message on Twitter or LinkedIn if you prefer, so I can have a look and help you.

  13. Will this not work if my column name has a number in it?

    I have to submit documents for 2 reviews, and I am using “1st Reviewer Status” and “2nd Reviewer Status” as the column names, but the above code will not populate the approved/rejected in that column. I modified the columns to “Reviewer One Status” and “Reviewer Two Status” and the code worked fine. But spelling out the values doesn’t look as clean, in my opinion.

    1. The problem is that list formatting uses the internal name for the columns. When creating it from the modern UI not all internal names are intuitive, especially with numbers and special characters.

      You can find the correct internal name for the column by accessing the ‘List Settings’ menu, then opening the column settings.

      You will see something like this in the browser URL after loading the Column Settings: /_layouts/15/FldEdit.aspx?List=%7BD436EDB0-7828-439E-9C2C-8CB6084F0B8F%7D&Field=_x0031_stReviewerStatus

      Note that you have at the end: Field=_x0031_stReviewerStatus, meaning that your field internal ID will be _x0031_stReviewerStatus on this case.

      So basically, grab the internal field names from there and use them wherever you need in the Formatting JSON.

  14. Hi! Thank you very much for this.
    It worked for me but I just have a problem.

    I changed a few properties to make the “Approve” and “Reject” appear as a button. It updates the record but the buttons and the txtcontent are always visible.

    How do I make the buttons disappear after being pressed and have the txtcontent appear only when the buttons are pressed?

    1. Hello, can you send me the source JSON so I can have a look? Message me on Twitter or LinkedIn if you prefer.

  15. Hi Michel, Thanks for the sample code, it works great.

    I am looking to lock the “Approval action by” column to prevent anyone from changing the approvers name once it’s been entered. Is there any way to do this?

    1. Hello Thomas,

      I recommend you do two actions:
      Disable the quick edit view
      Hide the ‘Approval Action By’ field from the forms.

      That will make it trickier for someone to change those fields.

      Another solution would be to run a Power Automate flow on the background and change the permissions of the item to be Read Only, so no one can edit it.

Leave a Reply

Your email address will not be published. Required fields are marked *