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
This post has been marked as an answer

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
};
Votes for this answer: 1
 
Soe Moe Tun
Reply

Hello,

Thank you Nicolai.

Best Regards,

Oliver

 

You must be logged in to post in the forum