Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create dynamic hyperlink longer than 255 characters in SharePoint Online

My setup:

  • SharePoint Online (part of Office 365)
  • No access to server coded (.NET) solutions
  • Document Library using the Document Set content type
  • New Experience UI enabled

Use case:

I have a SP2013 Workflow that allows a user to make a change request for a document in the library. The workflow has Initiation Form Parameters and the data supplied for those parameters, along with a reference to the item that the workflow was run on are written to another list in the site. This all works just fine.

What I'm trying to do is create a column in the document library that allows a user to navigate to the workflow's Initiation Form directly instead of having to right-click on the item, choose "Advanced" and then "Workflows".

The link to the workflow's Initiation Form page (taken right out of the browser's address bar when manually navigating to it) in total looks like this (line breaks added for readability):

https://company.sharepoint.com/sites/ABC/wfsvc/e73969f753574a3bb30c8d3ce3ab9c56/WFInitForm.aspx

?List={f9b73015-1131-442d-95b8-9682149a27e6}

&ID=5

&ItemGuid={71AA92CE-2D37-4D43-B593-AB6004E9DCF0}

&TemplateID={64193686-AB59-4D44-B0EB-FBD8E2CB7A1F}

&WF4=1

&Source=https%3A%2F%2Fcompany%2Esharepoint%2Ecom%2Fsites%2FABC%2FCourseDocuments%2FForms%2FCourseDocuments%2Easpx%3FRootFolder%3D%252Fsites%252FDCU%252FCourseDocuments%252FBasic%2520Stuff%26FolderCTID%3D0x0120D52000E334520C326BA440BF6F86F3CA80AE2800E3DBD1BD3A1EA348A9D944A931464C4D

The ID and ItemGuid portions of the link will need to be dynamic as they will contain a reference to the specific library document that the workflow will need to run against. Everything else is static.

To dynamically produce this URL per each item, I've created a second workflow that is run when a new item in the library is added as well as being able to be run manually (for items already in the library) and that workflow does correctly produce the URL needed for each item.

The Problem:

This URL is longer than the 255 characters that the "Hyperlink or Picture" column accepts and so the workflow errors out when trying to write this URL to the column.

What I've Tried:

I've been at this a while now and found several posted work-arounds, none of which have worked:

  • I've tried shortening the URL by making it relative (and so the full site URL can be removed) and placing that in the "Hyperlink or Picture" field but that resulted in a workflow error of "Invalid URL" even though the URL produced works when copied and pasted into the address bar.
  • I've tried shortening the URL by encoding the static parts with Bitly and this time the workflow completed and wrote a clickable URL to the field, however while the static parts work individually, when they are concatenated with the other parts, the final URL leads to a 404 error at the Bitly site.
  • I've made a "Calculated" column that is set to "Date/Time" result and made the calculation be a concatenation of parts of the URL into an HTML hyperlink syntax (i.e. ="<a href='"&[column1]&[column2]&[column3]&"'>Click</a>"). While this did succeed in getting the entire thing produced and set into the library, with all the dynamic parts correct, the field doesn't render as parsed HTML, instead the full HTML markup is rendered, so it's not a clickable link. (The image below shows a relative URL, but with this approach, I used an absolute URL. The picture is meant to just show the result of markup being produced and not parsed.)

    enter image description here

  • I've tried adding the "Full HTML content with formatting and constraints for publishing" field to my library (with the SharePoint Server Publishing Infrastructure Site Feature enabled) and got the same HTML markup being displayed as with the calculated column attempt above.
  • I've tried using a "Multi-line" text field and gotten the same markup display as above as well.
  • According to this article, there is no length limit for encoded URLs, so I tried encoding the entire URL and placing that into a "Hyperlink or Picture" field, but the workflow errors out on that with an "Invalid URL" message.

So, the bottom line is that I can create the URL needed but cannot find a way to get it placed into a field for each item in a way that makes it clickable as an actual hyperlink.


UPDATE:

In response to @Lukáš Nešpor suggestion below, I have tried variations of that but followed your instructions and tried again. I don't get the option for Column Formatting in the list itself, but I do get that option when configuring the column in List Settings, so that's where I entered the JSON.

enter image description here enter image description here

But, when I try it, the JSON formatting doesn't work.

enter image description here

like image 879
Scott Marcus Avatar asked Oct 16 '22 08:10

Scott Marcus


1 Answers

New user experience (in general)

You could leverage column formatting. It can be used in modern lists to change how the column (field) is rendered. One possible use is to render a link with properties of current item. Almost all fields can be referenced including ID, but GUID unfortunately not.

To resolve issue with GUID field (witn no-code), you could create text column in the list and call it e.g. Log Change Request. Then create simple Workflow and set this newly created column to current item's GUID. Don't forget to set the workflow to run when new item is created.

enter image description here

Then go to the list (using modern experience) and set column format.

enter image description here

Pane on the right will open. Paste bellow JSON to the field and save changes.

{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/column-formatting.schema.json",
  "elmType": "a",
  "txtContent": "Link",
  "attributes": {
    "href": {
      "operator": "+",
      "operands": [
        "https://company.sharepoint.com/sites/ABC/wfsvc/e73969f753574a3bb30c8d3ce3ab9c56/WFInitForm.aspx",
        "?List={f9b73015-1131-442d-95b8-9682149a27e6}",
        "&ID=",
        "[$ID]",
        "&ItemGuid=",
        "@currentField",
        "&TemplateID={64193686-AB59-4D44-B0EB-FBD8E2CB7A1F}",
        "&WF4=1",
        "&Source=https%3A%2F%2Fcompany%2Esharepoint%2Ecom%2Fsites%2FABC%2FCourseDocuments%2FForms%2FCourseDocuments%2Easpx%3FRootFolder%3D%252Fsites%252FDCU%252FCourseDocuments%252FBasic%2520Stuff%26FolderCTID%3D0x0120D52000E334520C326BA440BF6F86F3CA80AE2800E3DBD1BD3A1EA348A9D944A931464C4D"
      ]
    }
  }
}

Create item and when the Workflow finish, the column should contain the link you need.


Classic experience

For classic (legacy) view can be used Client Side Rendering. It do the same as column formatting in new experience.

Create text column and call it e.g. Log Change Request. Next step is to create Javascript file upload it to SharePoint (somewehere) and register this javascript as JSLink to the column.

1) Create Javascript file and call it e.g. log-change-request.js

// CSR-override for MDS enabled site
RegisterModuleInit("~site/SiteAssets/log-change-request.js", RegisterLink);

// CSR-override for MDS disabled site
RegisterLink(); 

function RegisterLink() {
  var field = {};
  field.Templates = {};
  field.Templates.Fields = {
    "LogChangeRequest": {
      "View": fieldTemplate
    }
  };

  SPClientTemplates.TemplateManager.RegisterTemplateOverrides(field);
}

function fieldTemplate(context) {
  var item = context.CurrentItem;
  return "<a href='"
    + "https://company.sharepoint.com/sites/ABC/wfsvc/e73969f753574a3bb30c8d3ce3ab9c56/WFInitForm.aspx"
    + "?List={f9b73015-1131-442d-95b8-9682149a27e6}"
    + "&ID=" + item.ID
    + "&ItemGuid=" + item.UniqueId
    + "&TemplateID={64193686-AB59-4D44-B0EB-FBD8E2CB7A1F}"
    + "&WF4=1"
    + "&Source=https%3A%2F%2Fcompany%2Esharepoint%2Ecom%2Fsites%2FABC%2FCourseDocuments%2FForms%2FCourseDocuments%2Easpx%3FRootFolder%3D%252Fsites%252FDCU%252FCourseDocuments%252FBasic%2520Stuff%26FolderCTID%3D0x0120D52000E334520C326BA440BF6F86F3CA80AE2800E3DBD1BD3A1EA348A9D944A931464C4D"
    + "'>"
    + "Link"
    + "</a>";
}

2) Upload this file to Site Assets to the site collection where you created the column Log Change Request. Note: this file can be placed anywhere you just have to change the path in it.
3) Download an install SharePoint Online Client Components SDK. It will copy some DLLs that are needed to connect to the SharePoint using PowerShell.
4) Run PowerShell script bellow which will set JSLink property of the column to the path to the Javascript file.

.NET CSOM solution how to set the column

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")

function Set-JSLink() {
  Param(
    [string]$SiteUrl,
    [string]$ListTitle,
    [string]$ColumnTitle,
    [string]$JSLinkUrl
  )

  $creds = Get-Credential

  $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
  $ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($creds.UserName, $creds.Password)

  $list = $ctx.Web.Lists.GetByTitle($ListTitle)
  $ctx.Load($list)
  $ctx.ExecuteQuery()

  $column = $list.Fields.GetByTitle($ColumnTitle)
  $column.JSLink = $JSLinkUrl
  # Make it read only so it is not visible in new or edit form
  $column.ReadOnlyField = $true
  $column.Update()

  $ctx.ExecuteQuery()
  $ctx.Dispose()
}

# Example:
Set-JSLink -SiteUrl "https://tenant.sharepoint.com/sites/ABC" -ListTitle "Document Sets" -ColumnTitle "Log Change Request" -JSLinkUrl "~site/SiteAssets/log-change-request.js"

JSOM solution how to set the column
Using this aproach does not require to install any SDK. Just place this HTML code to Script Editor.

<form>
  <input type="text" id="listTitle" placeholder="List title" /><br />
  <input type="text" id="columnTitle" placeholder="Column title" /><br />
  <input type="text" id="jsLink" placeholder="JSLink Url" /><br />
  <button onclick="setColumn(); return false;">Configure column</button>
</form>

<script type="text/javascript">
  'use strict';
  SP.SOD.executeFunc("sp.js")

  function setColumn() {
    var listTitle = document.getElementById("listTitle").value;
    var columnTitle = document.getElementById("columnTitle").value;
    var jsLink = document.getElementById("jsLink").value;

    var cc = new SP.ClientContext()
    var list = cc.get_web().get_lists().getByTitle(listTitle);
    cc.load(list);
    cc.executeQueryAsync(
      function () {
        var column = list.get_fields().getByTitle(columnTitle);
        column.set_jsLink(jsLink);
        column.set_readOnlyField(true);
        column.update();

        cc.executeQueryAsync(
          function () {
            alert("Column sucessfuly configured");
          },
          function (sender, args) {
            console.error(args.get_message());
          }
        );
      },
      function (sender, args) {
        console.error(args.get_message());
      }
    );

    cc.dispose();
  }

</script>

5) Open some Document Set, add document and the column should contain the link you need.

Note:

Because Document Set view is only in classic experience, it does not matter what is set in the settings (New or classic experience).

like image 163
Lukas Nespor Avatar answered Dec 18 '22 18:12

Lukas Nespor