Skip to content

Render a linked (chained) dropdown

Emit a <select> whose visible options are filtered client-side by a parent field's value. Trigger: Razor view calling the helper.

Field Value
Operation ID OP-21
Trigger Razor view calling the helper
Inputs Field name or lambda expression, parent field id, IEnumerable<LinkedSelectListItem>, removeDefault, html attributes
Outputs MvcHtmlString <select> markup
Primary components LinkedDropdownHelper.LinkedDropdownList and LinkedDropdownListFor
Entry point src/Web.Mvc/UI/Extensions/LinkedDropdownHelper.cs

Steps

  1. LinkedDropdownListFor converts the lambda to a property name through ExpressionHelper.GetExpressionText and delegates to LinkedDropdownList.
  2. Compute the element id by replacing . with _ in the name (BR-47).
  3. Build <select> with id, name, and data-parent-id="{parent}", then merge caller html attributes through ObjectExtensions.MergeAttributes, which concatenates rather than overwrites by default (BR-48).
  4. Add CSS classes {parent} and js-bo-ddl-chained — the client-side filter hook.*
  5. For each item, skip it when removeDefault is true and Value == "-1" (the conventional "please select" entry); otherwise emit an <option> whose CSS class is the item's LinkValue, with value, inner text, and selected when Selected is set (BR-49, BR-50).
  6. LinkedSelectList.GetListItems builds those items: it guards items non-null through Enforce, builds a case-insensitive HashSet of selected values, and for each source object evaluates DataValueField, DataTextField, and DataLinkedValueField through DataBinder.Eval (returning the object itself when the field expression is empty), marking Selected when the value is in the selected set (BR-51).

Process flow

The following diagram visualizes this operation's control flow.

flowchart TD
    Start([Razor view calls LinkedDropdownList])
    Id[Compute sanitized element id]
    Build[Build select with data-parent-id]
    Merge[Merge caller html attributes]
    Items[Evaluate GetListItems]
    Filter{removeDefault and value -1?}
    Skip([Skip option])
    Emit[Emit option element]
    EndOk([Return select markup])
    Start --> Id
    Id --> Build
    Build --> Merge
    Merge --> Items
    Items --> Filter
    Filter -->|Yes| Skip
    Filter -->|No| Emit
    Emit --> EndOk
    Skip --> EndOk

Failure and edge-case behavior

  • No unexpected failure paths beyond argument-guard exceptions and delegated dependency behavior were identified for this operation.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • src/Web.Mvc/UI/Extensions/LinkedDropdownHelper.cs