htmlblazorblazor-server-side

Blazor - Child component table rows not using parent component styling


I have a parent component with a html table which has its own elements, and then I have a child component with some div tags. My goal is to conditionally show the child component which would render the additional elements. Currently, the child component rows are displaying but they are not inheriting the styling from the the parent component. It just shows up as basic text without any styling at all. I even tried adding a ChildComponent.razor.css with duplicated classes in case the child component can't see the parent CSS, but that had no effect.

ParentComponent.razor:

<table id="tblPipeline" class="table table-bordered table-striped nowrap">
    <thead>
        <tr>
            <th style="width:30px;"></th>
            <th class="pipeline-column" @onclick="@(() => DoSort(0, "LoanNumber"))">
                <span className="@SortIconClass[0]"></span> loan number
            </th>
            
            <th class="pipeline-column hidden-xs hidden-sm" @onclick="@(() => DoSort(3, "FirstLoanProduct"))">
                <span [className]="sortIconClass[3]"></span> product
            </th>
        </tr>
    </thead>
    <tbody>
        <tr hidden="@(FilteredPipelines != null && FilteredPipelines.Count() > 0)">
            <td colspan="6" align="center">search returned no results</td>
        </tr>
        @if (FilteredPipelines != null)
        {
            @foreach (var context in FilteredPipelines)
            {
                <tr>
                    <td style="padding:0px;cursor:pointer;" @onclick="@(() => ShowHideDetails(context))">
                        <i class="fa fa-lg fa-angle-right icon-chfa" hidden="@context.ShowDetail"></i>
                        <i class="fa fa-lg fa-angle-down icon-chfa" hidden="@(!context.ShowDetail)"></i>
                    </td>
                    <td>
                        @*<span *ngIf="newLoanNumbers.indexOf(@context.LoanNumber) !== -1" style="color:red">New!</span>&nbsp;&nbsp;*@                                                    
                                    <span hidden="@(!context.IsConsolidatedReview)" style="font-weight:bold">@context.LoanNumber</span>
                        <span hidden="@context.IsConsolidatedReview">@context.LoanNumber</span>
                    </td>
                    <td>@context.FirstLoanProgram</td>
                </tr>

                @if (context.ShowDetail)
                {
                    <tr>
                        <td colspan="3">
                            <LoanDetail @ref="LoanDetailComponent" SelectedLoan="@context"></LoanDetail>
                        </td>
                    </tr>
                }
            }
        }
    </tbody>
    <tfoot>
    </tfoot>
</table>

private LoanDetail? LoanDetailComponent { get; set; }

public IQueryable<PipelineItemModel>? FilteredPipelines
{
    get
    {
        var results = Pipelines?.Items.AsQueryable();

        return results;
    }
}

public async Task ShowHideDetails(PipelineItemModel data)
{
    //flip the detail flag
    data.ShowDetail = !data.ShowDetail;

    }
}

ParentComponent.razor.css:

.loan-detail-group-label {
    width: 29%;
    float: left;
    overflow: hidden;
    background-color: #eeeeee;
    border-style: solid;
    border-width: thin;
    border-right-width: 0px;
    border-color: silver;
    border-top-left-radius: 4px;
    border-bottom-left-radius: 4px;
    text-align: right;
    padding-top: 5px;
    padding-right: 7px;
    padding-bottom: 5px;
    padding-left: 0px;
    margin-top: 2px;
    margin-bottom: 2px;
    height: 34px;
    font-weight: bold;
}

.loan-detail-group-data {
    width: 67%;
    float: left;
    overflow-x: hidden;
    overflow-y: visible;
    white-space: pre-line;
    background-color: white;
    border-style: solid;
    border-width: thin;
    border-color: silver;
    border-top-right-radius: 4px;
    border-bottom-right-radius: 4px;
    text-align: left;
    padding-top: 6px;
    padding-right: 0px;
    padding-bottom: 5px;
    padding-left: 7px;
    margin-top: 2px;
    margin-bottom: 2px;
    height: 34px;
}

etc, the rest of the classes...

ChildComponent.razor:

<div class="card-body">
     class="loan-detail-group-container">

    <div style="display: grid;grid-template-columns: 29% 100%; margin-bottom: 5px; ">
        <div class="loan-detail-group-label" style="width: 100%; height: 100%;">address</div>
        <div class="loan-detail-group-data" style="height: 100%;" xstyle="height: 56px;">@SelectedLoan.Address</div>
    </div>

    <div class="loan-detail-group-label">lock date</div>
    <div class="loan-detail-group-data">@SelectedLoan.ReservedDate </div>

    @if (SelectedLoan.BorrowerPhone != null)
    {
        <div class="loan-detail-group-label">borrower phone</div>
        <div class="loan-detail-group-data">@SelectedLoan.BorrowerPhone</div>
    }
    </div>
</div>

@code {

    [Parameter]
    public PipelineItemModel? SelectedLoan { get; set; }

    protected async override Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
    }
}

Solution

  • You could use the ::deep which will help you to scope and apply styles to child components. Or you could explicitly passed the CSS class names as parameters from the parent component to the child component:

    <LoanDetail 
        SelectedLoan="@context" 
        LabelClass="loan-detail-group-label" 
        DataClass="loan-detail-group-data" 
    />
    

    Dynamically applies these class names:

    <div class="@LabelClass">Address</div>
    <div class="@DataClass">@SelectedLoan.Address</div>
    

    Here is the sample code i have prepared with using ::deep:

    ParentComponent.razor:

    @page "/parent"
    @using BlazorApp2.Data
    @rendermode InteractiveServer
    <h3>Parent Component - HTML Table</h3>
    
    <table id="tblPipeline" class="table table-bordered table-striped nowrap">
        <thead>
            <tr>
                <th style="width:30px;"></th>
                <th class="pipeline-column" @onclick="@(() => DoSort(0, "LoanNumber"))">
                    <span></span> Loan Number
                </th>
                <th class="pipeline-column hidden-xs hidden-sm" @onclick="@(() => DoSort(3, "FirstLoanProduct"))">
                    <span></span> Product
                </th>
            </tr>
        </thead>
        <tbody>
            <tr hidden="@(FilteredPipelines != null && !FilteredPipelines.Any())">
                <td colspan="6" align="center">Search returned no results</td>
            </tr>
            @if (FilteredPipelines != null)
            {
                @foreach (var context in FilteredPipelines)
                {
                    <tr>
                        <td style="padding:0px;cursor:pointer;" @onclick="@(() => ShowHideDetails(context))">
                            <i class="fa fa-lg fa-angle-right icon-chfa" hidden="@context.ShowDetail"></i>
                            <i class="fa fa-lg fa-angle-down icon-chfa" hidden="@(!context.ShowDetail)"></i>
                        </td>
                        <td>
                            <span hidden="@(!context.IsConsolidatedReview)" style="font-weight:bold">@context.LoanNumber</span>
                            <span hidden="@context.IsConsolidatedReview">@context.LoanNumber</span>
                        </td>
                        <td>@context.FirstLoanProduct</td>
                    </tr>
    
                    @if (context.ShowDetail)
                    {
                        <tr>
                            <td colspan="3">
                                <LoanDetail SelectedLoan="@context" />
                            </td>
                        </tr>
                    }
                }
            }
        </tbody>
    </table>
    
    @code {
        private List<PipelineItemModel> Pipelines = new();
        private LoanDetail? LoanDetailComponent { get; set; }
    
        public IEnumerable<PipelineItemModel>? FilteredPipelines => Pipelines.AsQueryable();
    
        protected override void OnInitialized()
        {
            // Sample data
            Pipelines = new List<PipelineItemModel>
            {
                new PipelineItemModel { LoanNumber = "LN-001", FirstLoanProduct = "Product A", Address = "123 Main St", ReservedDate = DateTime.Now, BorrowerPhone = "123-456-7890", IsConsolidatedReview = false },
                new PipelineItemModel { LoanNumber = "LN-002", FirstLoanProduct = "Product B", Address = "456 Elm St", ReservedDate = DateTime.Now.AddDays(-1), BorrowerPhone = "987-654-3210", IsConsolidatedReview = true },
                new PipelineItemModel { LoanNumber = "LN-003", FirstLoanProduct = "Product C", Address = "789 Oak St", ReservedDate = DateTime.Now.AddDays(-2), BorrowerPhone = null, IsConsolidatedReview = false }
            };
        }
    
        public async Task ShowHideDetails(PipelineItemModel data)
        {
            data.ShowDetail = !data.ShowDetail;
        }
    
        public void DoSort(int column, string propertyName)
        {
            // Add sorting logic here if needed
            Console.WriteLine($"Sorting by column {column} with property {propertyName}");
        }
    }
    

    ParentComponent.razor.css:

    ::deep .loan-detail-group-label {
        width: 29%;
        float: left;
        overflow: hidden;
        background-color: #eeeeee;
        border-style: solid;
        border-width: thin;
        border-right-width: 0px;
        border-color: silver;
        border-top-left-radius: 4px;
        border-bottom-left-radius: 4px;
        text-align: right;
        padding: 5px 7px;
        margin: 2px 0px;
        height: 34px;
        font-weight: bold;
    }
    
    ::deep .loan-detail-group-data {
        width: 67%;
        float: left;
        overflow-x: hidden;
        overflow-y: visible;
        white-space: pre-line;
        background-color: white;
        border-style: solid;
        border-width: thin;
        border-color: silver;
        border-top-right-radius: 4px;
        border-bottom-right-radius: 4px;
        text-align: left;
        padding: 6px 7px;
        margin: 2px 0px;
        height: 34px;
    }
    
    table tbody tr:hover {
        background-color: #f9f9f9;
    }
    /* Highlight expanded rows */
    table tbody tr.expanded-row {
        background-color: #e6f7ff;
        border-left: 3px solid #1890ff;
    }
    

    LoanDetail.razor:

    @using BlazorApp2.Data
    <div class="card-body">
        <div style="display: grid;grid-template-columns: 29% 100%; margin-bottom: 5px;">
            <div class="loan-detail-group-label">Address</div>
            <div class="loan-detail-group-data">@SelectedLoan.Address</div>
        </div>
    
        <div class="loan-detail-group-label">Lock Date</div>
        <div class="loan-detail-group-data">@SelectedLoan.ReservedDate.ToShortDateString()</div>
    
        @if (!string.IsNullOrEmpty(SelectedLoan.BorrowerPhone))
        {
            <div class="loan-detail-group-label">Borrower Phone</div>
            <div class="loan-detail-group-data">@SelectedLoan.BorrowerPhone</div>
        }
    </div>
    
    @code {
        [Parameter]
        public PipelineItemModel SelectedLoan { get; set; } = new();
    }
    

    enter image description here