@typeparam TItem where TItem : BaseModel

<Select Mode="tags" TItem="Guid" TItemValue="Guid" @bind-Values="@SelectedValues" OnSelectedItemsChanged="OnSelectedItemsChanged" EnableSearch>
    <SelectOptions>
        @foreach (var entity in Entities.OrderBy(OptionLabelSelector))
        {
            <SelectOption TItemValue="Guid" TItem="Guid" Value="@entity.Id" Label="@OptionLabelSelector.Invoke(entity)" />
        }
    </SelectOptions>
</Select>

@code {
    [Parameter] public Func<TItem, string> OptionLabelSelector { get; set; }
    [Parameter] public IEnumerable<TItem> Entities { get; set; }

    [Parameter] public ICollection<TItem> Values { get; set; }
    [Parameter] public EventCallback<ICollection<TItem>> ValuesChanged { get; set; }

    private IEnumerable<Guid> SelectedValues
    {
        get
        {
            return Values?.Select(e => e.Id);
        }
        set
        {
            if (value != null)
                Values = value.ToList() as ICollection<TItem>;
        }
    }

    private async Task OnSelectedItemsChanged(IEnumerable<Guid> values)
    {
        var toAdd = values.Where(v => !Values.Any(e => e.Id == v)).ToList();
        var toRemove = Values.Where(e => !values.Any(v => v == e.Id)).ToList();

        foreach (var value in toAdd)
        {
            Values.Add(Entities.First(e => e.Id == value));
        }

        foreach (var value in toRemove)
        {
            Values.Remove(value);
        }

        if (ValuesChanged.HasDelegate)
            await ValuesChanged.InvokeAsync(Values);

        StateHasChanged();
    }
}
