Developer forum

Forum » Dynamicweb 10 » Custom-Selector

Custom-Selector

Soe Moe Tun
Reply

Dear Dynamicweb,

Is there a way where we can create custom-selector like product-group-selector as in pic, and in there data are taken from outside dynamicweb? 

Thanks

Best Regards,

Oliver


Replies

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Hi

Yes, you can implement a selector provider:

https://doc.dynamicweb.dev/api/Dynamicweb.CoreUI.Editors.Selectors.SelectorProviderBase.html

Here is an example of our provider for the above selector:

public class ProductGroupSelectorProvider : SelectorProviderBase<string>, IProductGroupSelectorProvider, ISelectorProviderWithLinkValue
{
    private const int ColumnCount = 1;
    private static NavigationNodePath BasePath => new(typeof(ProductsArea).FullName);
    public Icon LinkIcon { get => Icon.Folder; }
    public string LinkType { get => "product-group"; }
    public string LinkName { get => "Product group"; }
    public bool ShowShops { get; set; } = true;
    public bool ShowChannels { get; set; } = true;
    public bool ShowWarehouses { get; set; } = true;
    public bool ShowDataStructures { get; set; } = true;
    public bool ShowDataModels { get; set; } = true;
    public bool AllowShopSelection { get; set; } = true;
    public List<string>? UnselectableGroupIds { get; set; }
    public List<string>? HiddenGroupIds { get; set; }

    public ProductGroupSelectorProvider() : base(ColumnCount)
    { }

    public override SelectorDefinitionModel GetDefinition()
    {
        return new()
        {
            ColumnCount = ColumnCount,
            Heading = AllowShopSelection ? "Select" : "Select group"
        };
    }

    protected override UiComponentBase? GetColumnContent(int columnIndex) => columnIndex switch
    {
        1 => GetGroupList(),
        _ => null
    };

    private ShowScreen GetGroupList()
    {
        return new ShowScreen
        {
            Value = typeof(TreeScreen),
            Query = new GroupNavigationByPathQuery
            {
                Path = BasePath.Path,
                DisplayState = NavigationComponentDisplayState.Minimal,
                ShowShops = ShowShops,
                ShowChannels = ShowChannels,
                ShowWarehouses = ShowWarehouses,
                ShowDataStructures = ShowDataStructures,
                ShowDataModels = ShowDataModels,
                AllowShopSelection = AllowShopSelection,
                ShouldReturnValueAsLink = true,
                UnselectableGroupIds = UnselectableGroupIds,
                HiddenGroupIds = HiddenGroupIds
            },
            Load = ShowScreen.LoadMethod.Inline
        };
    }

    public override IEnumerable<SelectedItem>? GetSelectedItems(IEnumerable<string> selectedValues)
    {
        if (selectedValues is not null)
        {
            var query = new ProductCatalogGroupByIdQuery();
            return selectedValues.Select(groupId =>
            {
                if (string.IsNullOrWhiteSpace(groupId))
                    return new SelectedItem()
                    {
                        Id = groupId,
                        Name = groupId,
                        IsInvalid = true
                    };
                query.Id = groupId;
                var group = query.GetModel();
                return GetSelectedItemFromGroup(groupId, group?.Name ?? groupId);
            });
        }

        return null;
    }

    internal static SelectedItem GetSelectedItemFromGroup(string groupId, string groupName) => new()
    {
        Id = groupId,
        Name = groupName,
        Link = $"groupid={groupId}",
        DisplayName = $"{groupName} (ID: {groupId})",
    };

    public void ConfigureForLink(Link link)
    {
        ShowChannels = true;
        ShowWarehouses = true;
    }
}

Then we create the selector like this:

public static Selector CreateProductGroupSelector(ProductGroupSelectorOptions? options)
{
    options ??= new();
    
    var provider = AddInManager.GetInstance<IProductGroupSelectorProvider>()
        ?? throw new InvalidOperationException($"Unable to resolve instance of {typeof(IProductGroupSelectorProvider).FullName}.");

    provider.ShowShops = options.ShowShops;
    provider.ShowChannels = options.ShowChannels;
    provider.ShowWarehouses = options.ShowWarehouses;
    provider.ShowDataStructures = options.ShowDataStructures;
    provider.ShowDataModels = options.ShowDataModels;
    provider.AllowShopSelection = options.AllowShopSelection;
    provider.UnselectableGroupIds = options.UnselectableGroupIds;
    provider.HiddenGroupIds = options.HiddenGroupIds;

    var selector = CreateSelectorByProvider(provider as SelectorProviderBase<string>, options?.Hint, options?.Explanation, options?.Multiselect, Icons.Icon.Archive);

    if (!string.IsNullOrEmpty(options?.Value))
        selector.SetValue(options.Value);
    bool multiselect = options?.Multiselect ?? false;

    selector.EmptyStateText = multiselect ? "Select product groups" : "Search product group";
    selector.Hint = options?.Hint ?? (multiselect ? "Search or browse for product groups" : "Search or browse for a product group");
    selector.EmptyStateSearchText = "Search product groups";

    return selector;
}

And use it like this:

public override EditorBase? GetEditor(string propertyName, PageDataModel? model) => propertyName switch
{
    nameof(model.NavigationUseEcomGroups) => new Checkbox() { ReloadOnChange = true },
    nameof(model.NavigationProvider) => CreateNavigationProviderSelect(),
    nameof(model.NavigationParentType) => CreateNavigationParentTypeSelect(),
    nameof(model.NavigationGroups) => SelectorBuilder.CreateProductGroupSelector(new() { Multiselect = true }),
    nameof(model.NavigationShopId) => EditorHelper.GetShopEditor(),
    nameof(model.NavigationMaxLevels) => CreateNavigationMaxLevelsSelect(),
    nameof(model.NavigationProductPage) => SelectorBuilder.CreatePageSelector(areaId: model?.AreaId),
    _ => null
};
 
Soe Moe Tun
Reply

Hello,

Thank you Nicolai.

Best Regards,

Oliver

 

You must be logged in to post in the forum