The RfDropDownMulti works primarily with two parameters: SelectedItems and Items.
Binding the selection
The selection itself has two parameters: SelectedItems is the list of chosen items and
SelectedItemsChanged is raised after every click that changes the selection. Bind them
together with @bind-SelectedItems, or bind only SelectedItemsChanged and let the
drop down keep the list: the component starts an empty list on the first item click, adds the clicked item,
and emits SelectedItemsChanged, so the callback fires from the very first click even with no
SelectedItems parameter set. Later clicks add and remove items from that same list and every
emit carries it, so the callback alone is a complete selection contract. The list is started before the
MaxSelectableItems cap is consulted, so the cap and MaxSelectionKeepRule behave
identically whether or not you supply SelectedItems.
Example: selection via callback only
<RfDropDownMulti TItem="string"
Items="@Items"
SelectedItemsChanged="@OnSelectedChanged" />
private void OnSelectedChanged(List<string> selected)
{
// The first click on an item delivers a one item list; no SelectedItems parameter is needed.
}
How are Items Render?
The dropdown doesn't make any assumptions on how to render the items or selected items it is given.
Instead the drop down supports three RenderFragement to customize the way an item appears within the drop down.
All three RenderFragement have a context of TItem and are used to setup two sections.
The two sections of the drop down that can be custimized are RowItemTemplate and SelectedItemTemplate.
Row Item Template
The RowItemTempalte directly sets each row or option of the drop down. Each row is wrapped in the following code:
@RowItemTemplate(item)
If
RowItemTemplate isn't set the drop down will use
ChildContent.
Selected Items Template
When the drop down has a selection it calls the SelectedItemTemplate to render the TItem within the input portion of the drop down.
Each selected item is wrapped in the following code:
@SelectedItemTemplate(selectedItem)
If
SelectedItemTemplate isn't set the drop down will use
ChildContent.
Loading Items
When the items come from a service instead of a static list, set OnLoad. The drop down calls it with the
current filter text and expects your handler to assign Items. Clicking the trigger runs the open
sequence: the loading state is applied (Bulma shows the spinner on the trigger icon), OnLoad is
awaited, the loading state is cleared, and the panel opens only after your handler has returned.
An attempt to open while a load is in flight is ignored: no second OnLoad starts and the component
keeps the state of the load that is running. Typing in the filter re-invokes OnLoad with the new
filter text while the panel stays open; set FilterRateLimit to hold keystrokes until the rate elapses
and fire only the latest filter.
Filter rate limiting
While the panel stays open, every keystroke in the filter box queues a filter change instead of calling
OnLoad directly. When FilterRateLimit is greater than zero (the default is 250 ms)
the drop down waits until the newest keystroke has sat quietly for that many milliseconds, then makes one
OnLoad call with the latest filter text; keystrokes typed during the wait are superseded and
dropped. Any new keystroke restarts the wait, so the load fires on the trailing edge of the typing.
FilterRateLimit = 0 turns the wait off and fires on every keystroke.
The wait is measured on a monotonic clock (stopwatch timestamps) and each sleep is only the time remaining
in the quiet window, so the window length never depends on the wall clock: NTP corrections or manual clock
changes cannot stretch the debounce or break it.
Loader exceptions
The loading state is released in a finally, so a handler that throws cannot latch the drop down into a
permanent loading state. The failed attempt leaves the drop down closed, the exception still propagates to your
app's event handling (Blazor's unhandled exception path unless you catch it), and the next click calls
OnLoad again. Before this fix a throwing handler left the loading state set forever and the drop down
could never be opened again.
NOTE: If a load can fail and you still want the panel to open, catch the exception inside your
OnLoad handler: when the handler returns normally the panel opens with whatever you left in
Items; when it throws, the attempt ends closed.
Example: loading items on open
<RfDropDownMulti TItem="string"
Items="@Items"
@bind-SelectedItems="@Selected"
OnLoad="@LoadNames" />
private async Task LoadNames(string filter)
{
Items = await NameService.SearchAsync(filter);
}
Styling
The drop down passes four class parameters through to the elements it renders, so you can style it without fighting the component:
CssClass is added to the root div.dropdown element, alongside the state classes the
component manages itself (is-active while open, is-right and is-up from Position).
CssFilterClass is added to the filter textbox alongside the Bulma input class.
It has no effect while ShowFilter hides the filter.
CssRowItemClass is added to every option row inside the drop down panel.
CssSelectedClass is added to each selected item tag in the trigger.
Unset parameters add nothing: the rendered markup is identical to a drop down that never had them.
Example:
<RfDropDownMulti TItem="string"
Items="@Items"
@bind-SelectedItems="@Selected"
CssClass="wide-dropdown"
CssFilterClass="is-rounded" />
With the panel open this renders the root as class="dropdown is-active wide-dropdown",
each selection as class="tag", and the filter textbox as class="input is-rounded".