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

Time:09-17

I am loading data to a grid with 3 columns in Blazor. For the grid structure I have used Bootstrap rows and columns. If I need to highlight rows on hover and keep the row selected using onClick event what is the best way to achieve it?

Below is how I populate data.

<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>

Thanks.

CodePudding user response:

You need to maintain the rows selected state. Here is a generic view model to wrap any row type:

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

Then using style classes for both selected and hover:

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

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

I seperated the row into its own component UserRow.razor with a [Parameter] that takes the RowState<User> viewmodel.

This simplifies the logic to handle the click event and logic for the css class to highlight the row.

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" : "";
}

Refactoring your original code:

<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();
}

Here is a working REPL

CodePudding user response:

<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;
  }

}

CodePudding user response:

You can utilize Radio toggle buttons (for single selection) or Checkbox toggle buttons (for multiple) as Block buttons with just a little bit of custom styling. Put the whole user row inside the label and use the username or other unique field for the input id.

Here is an example using Radio toggle buttons:

label.btn {
  border: none;
  border-radius: 0;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/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>

  • Related