Provisioning Cross-site Lookup Fields
Under the hood, Cross-site Lookup field is very similar to a regular lookup field but with its own rendering mechanism that is implemented in a script specified in JSLink property and additional configuration defined in a field schema under the ‘csl’ namespace. You will find those extra properties as well as JSLink value in the samples below. In this article, I will demonstrate how to add a new Cross-site Lookup field, change the source list of an existing lookup, and copy configuration from one site to another programmatically by using PowerShell and CSOM.
To get started, you should download and install SharePoint Client SDK for your SharePoint edition:
Next, include CSOM libraries at the begining of your PowerShell script:
for SharePoint Online:
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll" Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
for SharePoint on-premises (2013/2016):
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll" Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Creating a new field
A Cross-site Lookup field has some special attributes in contrast to an ordinary Lookup field:
$tFieldSchema = @" <Field Type="Lookup" Name="$targetFieldInternalName" DisplayName="$targetFieldTitle" JSLink="~site/crosssitelookupapplib/clienttemplates.js?field=$targetFieldInternalName" xmlns:csl="Plumsail.CrossSiteLookup" csl:ShowNew="false" csl:RetrieveItemsUrlTemplate="function (term, page) {
 if (!term || term.length == 0) {
 return "{WebUrl}/_api/web/lists('{ListId}')/items?`$select=Id,{LookupField}&`$orderby=Created desc&`$top=10";
 }
 return "{WebUrl}/_api/web/lists('{ListId}')/items?`$select=Id,{LookupField}&`$orderby={LookupField}&`$filter=startswith({LookupField}, '" + encodeURIComponent(term) + "')&`$top=10";
}" csl:ItemFormatResultTemplate="function(item) {
 return '<span class="csl-option">' + item["{LookupField}"] + '</span>'
}" csl:NewText="Add new item" csl:NewContentType="" Mult="FALSE" WebId="$lookupWebID" List="$lookupListID" ShowField="$lookupField" /> "@
Any ordinary lookup field can be converted to the Cross-site lookup field as easy as adding the additional attributes under the ‘csl’ namespace and changing the JSLink property.
You can download the complete sample and adjust it accordingly to your needs.
Repairing Cross-site lookup fields
After importing a site template containing Cross-site Lookup fields pointing to lists or libraries from other sites, all those fields will become broken since they are linked to source lists by ID. To repare those links, you can use the script below. It replaces corrupted IDs in a field’s schema with correct values:
$field.SchemaXml = $field.SchemaXml.Replace($field.LookupWebId.ToString(), $lookupWebID.ToString()) $field.SchemaXml = $field.SchemaXml.Replace($field.LookupList.ToString(), $lookupListID.ToString()) $field.Update() $tCtx.ExecuteQuery()
You can download the complete sample and adjust it accordingly to your needs.
Copying Cross-site lookup field from one site to another
Imagine that you are configuring Cross-site Lookup fields on a development site and want to trasfer their configuration to the production one without opening Cross-site Lookup manager and reproducing the same configuration. The script below does what you need. It creates a new Cross-site Lookup field on a target site and copies configuration of an existing field from another site.
# Getting configuration of the source field [xml] $xml = $sField.SchemaXml $showNew = $xml.Field.ShowNew $retrieveItemsUrlTemplate = [Security.SecurityElement]::Escape($xml.Field.RetrieveItemsUrlTemplate) $itemFormatResultTemplate = [Security.SecurityElement]::Escape($xml.Field.ItemFormatResultTemplate) $newText = $xml.Field.NewText $mult = $xml.Field.Mult $showField = $xml.Field.ShowField Write-host "Source field schema : " $sField.SchemaXml # Creating schema of a new field $tFieldSchema = @" <Field Type="Lookup" Name="$targetFieldInternalName" DisplayName="$targetFieldTitle" JSLink="~site/crosssitelookupapplib/clienttemplates.js?field=$targetFieldInternalName" WebId="$lookupWebId" List="$lookupListId" xmlns:csl="Plumsail.CrossSiteLookup" csl:ShowNew="$showNew" csl:RetrieveItemsUrlTemplate="$retrieveItemsUrlTemplate" csl:ItemFormatResultTemplate="$itemFormatResultTemplate" csl:NewText="$newText" csl:NewContentType="" Mult="$mult" ShowField="$showField" /> "@ # Creating a field $tList = $tCtx.Web.Lists.GetByTitle($targetList) $field = $tList.Fields.AddFieldAsXml($tFieldSchema, $True, [Microsoft.SharePoint.Client.AddFieldOptions]::AddFieldInternalNameHint) $tCtx.ExecuteQuery()
You can download the complete sample and adjust it accordingly to your needs.
Summary
A Cross-site Lookup field has a very similar schema as a regular lookup field but provides some additional properties under the ‘csl’ namespace. With the help of the scripts described in this article, you can add new Cross-site Lookups, convert regular Lookups to Cross-site Lookups, repair Cross-site Lookups after creating a site from a template, and copy configuration of a Cross-site Lookup field from one site to another.