From Droplist to Droplink
During some maintenance on older projects, I came across the usage of the Sitecore field Droplist.
This immediately triggered my spidey sense! Droplists can be used in a project but they have a major drawback. They only stores the String value and not the GUID of the selected item.
The project uses multiple languages and since we actually needed to translate several items that had this Droplist field, we needed to make some changes.
Let's look at a simple scenario.
We have defined Blog Categories and we have a template Blog Page.
The Blog Page itself has a field that references a Blog Category.
You can safely change the type of a field from Droplist to Droplink.
But be aware that when changing the type, you will not change the values that were already selected.
So in the case of the example, Blog Post 1 still contains the 'raw' text value: Demo category 1.
And you'll see the warning: The field contains a value that is not in the selection list.
We need to update all fields so that they reference with a GUID instead of pure text.
The PowerShell script
We can leverage PowerShell to update the values. You need the following:
- Path to the items that you want to update. In our case the Blog Pages.
- Path to the datasource for the droplink. So for this example this is Blog Categories
- The FieldName to get the current value, search for the new
# Script to update the Blog Category on Blog Pages
# Run after changing the field type from Droplist to Droplink
$path = "master:\sitecore\content\Home\Blog Pages"
$items = Get-ChildItem -Path $path
$items | ForEach-Object {
$item = $_
# Search for the Blog Category based on the text value of the field
$foundItem = Get-ChildItem -Path "/sitecore/content/Global/Blog Categories" | Where-Object { $_.Name -eq $item."Blog Category" }
Write-Host "$($item.Name) - $($item.{Blog Category}) - $($foundItem.ID)"
# Update the Blog Category field on the Blog Page
$item.Editing.BeginEdit()
$item.Fields["Blog Category"].Value = $foundItem.ID
$item.Editing.EndEdit()
}
Side note: since the field is named Blog Category, which contains a space, we need quotes or brackets to run the script. That is why $item."Blog Category" is defined and alternatively we can use $item.{Blog Category}
Important: This script will update all the Blog Category fields of the items you defined in the path variable.
If for some reason the text value you had, did not exist in the list, it will be updated to an empty value.
This is the case for Blog Page 4 which had the text 'Non-existing category'. This category is not in the list, is not a valid value and will get emptied.
Running the script will result in changing the values from text to a GUID, making your droplink fields usable again:
Please take note of the output of the script too. It will list the item that was edited and the result of the 'EndEdit' method is either True, when at least 1 field was changed. And false when no fields were changed.
Bonus: PowerShell script to discover Droplist fields
You can use this script to discover all droplist fields for a given path. Use them on your User Defined, Feature, Foundation and Project folders to discover all templates that have a droplist field.
$startPath = "master:/sitecore/templates/Project"
Write-Host "Search started $(Get-Date -format 'u')"
$list = [System.Collections.ArrayList]@()
$itemsToProcess = Get-ChildItem $startPath -Language * -Recurse
if($itemsToProcess -ne $null) {
$itemsToProcess | ForEach-Object {
$match = 0;
# TemplateId corresponds to this field: System/Templates/Template field
# We're only interested in Template fields which have Droplist as its value. The fields are items underneath a template, so we need to loop those.
if($_.TemplateID -eq "455A3E98-A627-4B40-8035-E683A0331AC7" -and $_.Fields["Type"].Value -eq 'Droplist' ){
$info = [PSCustomObject]@{
"ID"=$_.ID
"Language"=$_.Language
"TemplateName"=$_.TemplateName
"FieldName"=$_.Name
"FieldType"=$_.Type
"FieldValue"=$_.ItemPath
}
[void]$list.Add($info)
}
}
}
Write-Host "Search ended $(Get-Date -format 'u')"
Write-Host "Items found: $($list.Count)"
$list | Format-Table