4

According to the docs, you can add items to a list field in forms either as a static set of values, or a dynamic datasource. However, I need to create a field that can switch the datasource on the fly, based on the selection of another field.

For example, if City A is selected in a previous dropdown field, then the offices from that city should be shown. Likewise, City B would show the offices from that city. I have setup two different datasources, but cannot figure out any intuitive way to setup a way for them to switch.

I've considered several hacks, such as putting two dropdown fields (one for each city) and showing/hiding the relevant one, but as the cities list grows this will become cumbersome. In addition, the field is required, so hiding it and leaving it blank doesn't seem like it would work.

Is this something that requires a custom field to function the way I want it to, and if so where can I find info on how to create such a thing?

Is there an easy, simple way to achieve this?

1
1

I have come across the same need. In my case, I had to get Provinces or States according to a Selected Country. My country dropdown has only USA and Canada, which makes my case a lot easier, but I guess you can take whatever from my use case and update according to yours. Here is what I did :

In master database

I have created my datasources for country, provinces and states within my shared data that will be serialized.

Create the template of the item that will own the dynamic datasource(in my case, called ProvinceState template)

Add fields for each datasources (in your case it might be too much, you can see later on what could be done, but for me I only needed Provinces and States to be filled.. and I wanted both of them to be loaded in my items so whenever I switched datasource, I dont make any call as they are stored...)

Add standard values on this template and also give it default values as for the datasource item.

In core database (I am using Sitecore rocks for this part, I would consider using it for any forms related development, else its getting messy.)

Create a new Field Setting here /sitecore/client/Applications/FormsBuilder/Components/Layouts/PropertyGridForm/PageSettings/Settings/YOUR NEW FIELD by right-clicking on Settings + add new item + find Form Parameters template. From there you can duplicate from other Field settings the necessary Form Sections or create by right clicking and chosing the one needed (Details, Validation, Styling, Conditions and Advanced). For this steps, please take a look at the official Sitecore documentation as well.

We now want to add a viewModel and a view for our field.

Create your formextension projects and its desired project structure. Create your viewModel and extend ListViewModel public class ProvinceStateViewModel : ListViewModel

In my case, there I have created a list of ListFieldItem prop for each datasources (USA'States and CANADA's province) and define a database prop

 private Database MasterDatabase { get; set; }
 public List<ListFieldItem> ProvinceItems { get; set; }
 public List<ListFieldItem> StateItems { get; set; }

you want to override these methods InitItemProperties and UpdateItemFields

The InitItemProperties is called when you drag and drop your field in the field editor. This is where I put my logic in getting my datasources filled with the values from my cms.

The item passed to the methods is based on the template created earlier, so I can get both my datasources item from there. This code is not in production state, you should take it only as an example.

MasterDatabase = Sitecore.Configuration.Factory.GetDatabase("master");
//return or log whatever if something goes wrong with the db here. Should not, but if it does, should have something in mind here.
ProvinceDatasource = item.Fields["ProvinceDatasource"]?.Value;
if (!string.IsNullOrEmpty(ProvinceDatasource))
{
    ProvinceItems = new List<ListFieldItem>();
    SetProvinceStateDatasource(ProvinceDatasource, ProvinceItems);
}      

StateDatasource = item.Fields["StateDatasource"]?.Value;
if (!string.IsNullOrEmpty(StateDatasource))
{
    StateItems = new List<ListFieldItem>();
    SetProvinceStateDatasource(StateDatasource, StateItems);
}

private void SetProvinceStateDatasource(string provinceStateDatasource, List<ListFieldItem> provinceStateList)
{
    var provinceStateDatasourceItem = MasterDatabase.GetItem(new ID(provinceStateDatasource));

    if (provinceStateDatasourceItem != null && provinceStateDatasourceItem.TemplateID == Templates.Country.TemplateID)
    { 
        foreach (Item children in provinceStateDatasourceItem.Children)
        {
            if (children.TemplateID == Templates.ProvinceState.TemplateID)
            {
                var provinceStateFieldValue = children.Fields["ProvinceState Name"]?.Value;
                if (!string.IsNullOrEmpty(provinceStateFieldValue))
                {
                    provinceStateList.Add(new ListFieldItem
                    {
                        ItemId = children.ID.ToString(),
                        Text = children.Fields["ProvinceState Name"]?.Value,
                        Value = children.Fields["ProvinceState Name"]?.Value
                    });
                }
            }
        }
    }
}

And the UpdateItemFields is called on save. So here I only have this done :

protected override void UpdateItemFields(Item item)
{
    base.UpdateItemFields(item);

    item.Fields["ProvinceDatasource"]?.SetValue(ProvinceDatasource, true);
    item.Fields["StateDatasource"]?.SetValue(StateDatasource, true);
}

Now, we want to add a view. Create it in your project so the strucutre is like : Views/FormBuilder/FieldTemplates Make sure that you are using the Model.Value for Label and select id as it used by @Html.GenerateUnobtrusiveValidationAttributes(m => m.Value) and it gets pretty messy to try with something else. Within my little css tricks, that where I switch my datasource on select. So again, my use case seems easier than yours. You might want to do something else. But for smal amount of different datasources, I think it does the trick.

@model Parametric.Feature.FormsExtensions.Fields.ProvinceStateViewModel

@using Sitecore.ExperienceForms.Mvc.Html

<label @Html.IdFor(m => Model.Value) class="@Model.LabelCssClass">ProvinceState</label>

<select id="@Html.IdFor(m => Model.Value)"
        name="@Html.NameFor(m => Model.Value)"
        class="@Model.CssClass"
        data-sc-tracking="@Model.IsTrackingEnabled"
        data-sc-field-name="@Model.Name"
        data-sc-field-key="@Model.ConditionSettings.FieldKey" @Html.GenerateUnobtrusiveValidationAttributes(m => m.Value)>

    <option label=""></option>
    @foreach (var item in Model.ProvinceItems)
    {
        <option class="provinces" value="@item.Value" selected="@item.Selected">@item.Text</option>
    }

    @foreach (var item in Model.StateItems)
    {
        <option class="states" value="@item.Value" selected="@item.Selected">@item.Text</option>
    }

</select>

@Html.ValidationMessageFor(m => Model.Value)

<script>
    $('.whateverSelectCssClass').change(function () {
        if ($(this).val() === "Canada") {
            $('option[class="provinces"]').css('display', 'inherit');
            $('option[class="states"]').css('display', 'none');
        }
        else if ($(this).val() === "United States") {
            $('option[class="provinces"]').css('display', 'none');
            $('option[class="states"]').css('display', 'inherit');
        }
        else {
            $('option[class="states"]').css('display', 'none');
            $('option[class="provinces"]').css('display', 'none');
        }
    })

    $(document).ready(function () {
        $('option[class="states"]').css('display', 'none');
        $('option[class="provinces"]').css('display', 'none');
    });
</script>

Now, we need to wrap it up by creating the field type in the master database. Go to : /sitecore/system/Settings/Forms/Field Types and add your fieldType (in my case Province State, and also used the same icon as the template created earlier.) You need to fill these fields :

  • View Path (FieldTemplates/YourView)
  • Model Type (namespace.CustomViewModel, namespace)
  • Allowed validations (check other fields that are similar and pick the same if needed)
  • Property Editor (pick the item created earlier in the core database)
  • Field Template (pick your previously created template)

To enable conditions on your field, you have to go there : /sitecore/system/Settings/Forms/Meta Data/Conditions/Action Types, choose your conditions and add your field type in the Allowed Field Type field.

Build, publish, etc.

When building a form, use a normal dropdowndownlist field and chose you main datasource. Add a css class (the one used in the within the view, in this example whateverSelectCssClass) in the Styling section, css class field. And should be good to go. Hope it helps ..!

Again, lot of code here, make sure you udpate accordingly, it is not prod-ready. Cheers.

-3

I know its quite late, but it might help someone else :)

Please see the below article for its resolutions:

http://surbhikochhar.in/technology/sitecore/custom-drop-down-list-for-sitecore-9-forms/

2
  • This is a link only answer. You can improve this answer by adding code snippets and images to explain how you solve this issue. – Pete Navarra Nov 29 '18 at 0:24
  • In fact, I just tried the link and its dead? – David Walker Apr 5 at 23:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.