在 Bootstrap 中,如何在悬停时突出显示网格行并使其在单击时被选中?

How do I highlight a grid row on hover and make it selected on click in Bootstrap?

我正在将数据加载到 Blazor 中具有 3 列的网格。对于网格结构,我使用了 Bootstrap 行和列。如果我需要在悬停时突出显示行并使用 onClick 事件保持选中行,实现它的最佳方法是什么?

下面是我如何填充数据。

<div class="container-fluid">
    <div class="row">
        <div class="col">User Name</div>
        <div class="col">First Name</div>
        <div class="col">Last Name</div>
    </div>

    @foreach (var user in users)
    {
        <div class="row">
            <div class="col">@user.UserName</div>
            <div class="col">@user.FirstName</div>
            <div class="col">@user.LastName</div>
        </div>
    }
</div>

谢谢。

您可以利用 Radio toggle buttons (for single selection) or Checkbox toggle buttons (for multiple) as Block buttons 只需一点自定义样式。将整个用户行放在标签内,并使用用户名或其他唯一字段作为输入 ID。

这是一个使用单选按钮的例子:

label.btn {
  border: none;
  border-radius: 0;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">

<div class="container-fluid">
  <div class="row">
    <div class="col-4">User Name</div>
    <div class="col-4">First Name</div>
    <div class="col-4">Last Name</div>
  </div>

  <div class="row">
    <!-- @foreach (var user in users)
    { -->
    <div class="col-12 d-grid p-0">
      <input type="radio" class="btn-check" name="options" id="@user.UserName" autocomplete="off">
      <label class="btn btn-outline-dark text-start" for="@user.UserName">
        <div class="row">
          <div class="col-4">@user.UserName</div>
          <div class="col-4">@user.FirstName</div>
          <div class="col-4">@user.LastName</div>
        </div>
      </label>
    </div>
    <!-- } -->

    <div class="col-12 d-grid p-0">
      <input type="radio" class="btn-check" name="options" id="@user.UserName2" autocomplete="off">
      <label class="btn btn-outline-dark text-start" for="@user.UserName2">
        <div class="row">
          <div class="col-4">@user.UserName2</div>
          <div class="col-4">@user.FirstName</div>
          <div class="col-4">@user.LastName</div>
        </div>
      </label>
    </div>
    <div class="col-12 d-grid p-0">
      <input type="radio" class="btn-check" name="options" id="@user.UserName3" autocomplete="off">
      <label class="btn btn-outline-dark text-start" for="@user.UserName3">
        <div class="row">
          <div class="col-4">@user.UserName3</div>
          <div class="col-4">@user.FirstName</div>
          <div class="col-4">@user.LastName</div>
        </div>
      </label>
    </div>

  </div>
</div>

<table class="table table-hover">
<tr>
    <td >User Name</td>
    <td >First Name</td>
    <td >Last Name</td>
</tr>

@foreach (var user in users)
{
    string bg = (user.Id == selectedUserId)? "bg-info" : "";
    <tr class=@bg @onclick=@SelectUser(user.Id) @key=user>
        <td >@user.UserName</td>
        <td >@user.FirstName</td>
        <td >@user.LastName</td>
    </tr>
}
@code{

  private int selectedUserId {get;set;} = 0;
  private void SelectUser(int userId){
   selectedUserId = userId;
  }

}

您需要保持行的选定状态。 这是包装任何行类型的通用视图模型:

public class RowState<TItem>
{
    public RowState(TItem item) => Item = item;
    public TItem Item { get; set; }
    public bool IsSelected { get; set; }
}

然后对选中和悬停使用样式 classes:

.hover-row:hover {
    background-color: #0000ff33;
}

.selected-row {
    background-color: #0000ff77;
}

我将行分隔成它自己的组件 UserRow.razor,其中 [Parameter] 采用 RowState<User> 视图模型。

这简化了处理点击事件的逻辑和 css class 突出显示该行的逻辑。

UserRow.razor

<div class="row hover-row @CssClass" @onclick="RowClicked" >
    <div class="col">@User.UserName</div>
    <div class="col">@User.FirstName</div>
    <div class="col">@User.LastName</div>
</div>

@code {
    [Parameter]
    public RowState<User> UserRowState { get; set; }   

    private void RowClicked() => UserRowState.IsSelected = !UserRowState.IsSelected;

    private User User => UserRowState.Item;
    private bool IsSelected => UserRowState.IsSelected;
    private string CssClass => IsSelected ? "selected-row" : "";
}

重构您的原始代码:

<div class="container-fluid">
    <div class="row">
        <div class="col">User Name</div>
        <div class="col">First Name</div>
        <div class="col">Last Name</div>
    </div>

    @foreach (var user in UserRows)
    {
        <UserRow UserRowState=user />     
    }
</div>

@code {
    IEnumerable<RowState<User>> UserRows = User.DemoData
        .Select(user => new RowState<User>(user))
        .ToList();
}

这是一个有效的 REPL

JavaScript 答案中的

None 适用于 Blazor。忽略他们。

如果你只想到select单行,你可以使用@Ali Borjian 的回答

为了跟踪select多行的离子,您可以使用以下两种方法之一:

  1. 使用 class 跟踪每行的状态信息。 这是 Brian 的回答。
  2. 创建一个辅助列表来跟踪哪些行被 selected。 如下。

.

<div class="container-fluid">
    <div class="row">
        <div class="col">User ID</div>
        <div class="col">User Name</div>
    </div>

    @foreach (var user in Users)
    {
        string CSS = SelectedUsers.Contains(user) ? " Selected" : "";
        <div class="row @CSS" style="" @onclick="()=>ToggleSelection(user)">
            <div class="col">@user.ID</div>
            <div class="col">@user.Name</div>
        </div>
    }
</div>

@code {
    class User { public int ID; public string Name;  }

    List<User> Users = new List<User> { new User { ID = 1, Name = "Benjamin" }, new User { ID = 2, Name = "John" }, new User { ID = 3, Name = "David" } };
    List<User> SelectedUsers = new();

    void ToggleSelection(User user)
    {
        if (SelectedUsers.Any(u => u == user)) SelectedUsers.Remove(user);
        else SelectedUsers.Add(user);
    }

}
<style>
    .row {cursor:pointer}
    .row:hover { background-color:#c2d8ff }
    .Selected {background-color: #4781e9}
    .Selected:hover {background-color: #83aefb}
</style>