skip to Main Content

I have searched everywhere and cant find an answer so any help would be greatly appreciated!

I have a ForEach loop on a razor page and it loops through a list of appointments each one has a different color (I watched the whole process in the debugger and the values.) but it only renders all of the looped items as the last color in the foreach loop.

Here is the loop

@foreach (var a in appt.ToList())
{
   <ApptCard @key="a.Text" Text="@a.Text" BoxColor="@users.Where(x => x.Id == a.Id).FirstOrDefault().Color"/>
}

Here is the Card that is being looped

@using System.Drawing

<style>
    .apptColor{
        background-color: @rgbaColor;
    }
</style>

<MudPaper Class="pa-2 apptColor">@($"{Text})</MudPaper>

@code {
    [Parameter] public string Text { get; set; } = null!;
    [Parameter] public string BoxColor { get; set; } = null!;
    private string rgbaColor;

    protected override Task OnInitializedAsync()
    {
            var color = ColorTranslator.FromHtml(BoxColor);
            int r = Convert.ToInt16(color.R);
            int g = Convert.ToInt16(color.G);
            int b = Convert.ToInt16(color.B);
            rgbaColor = string.Format("rgba({0}, {1}, {2}, {3});", r, g, b, .2);

        return base.OnInitializedAsync();
    }
}

the colors come from the database.

what’s rendered

In the picture the first one should be red, second brown, third green, and the fourth red.

2

Answers


  1. Razor/CSS Color Issue

    The problem you’re facing is because of how CSS is applied to your ApptCard components in a Razor page. The <style> tag you’re using isn’t limited to just the component but applies globally to the entire page. So, when you’re looping through your cards, each iteration updates the .apptColor class globally. Consequently, every ApptCard ends up with the background color from the last iteration of the loop.

    To fix this, you need to apply styles in a way that each ApptCard can have its own unique background color without interference. One solution is to directly include the background color style within the MudPaper component. This ensures that each card gets its own color without being overridden by later loop iterations.

    Here’s a revised version of your ApptCard that does this:

    @using System.Drawing
    
    <MudPaper Class="pa-2" style="background-color: @RgbaColor;">@($"{Text}")</MudPaper>
    
    @code {
        [Parameter] public string Text { get; set; } = null!;
        [Parameter] public string BoxColor { get; set; } = null!;
        private string RgbaColor => GetRgbaColor(BoxColor);
    
        private static string GetRgbaColor(string hexColor)
        {
            var color = ColorTranslator.FromHtml(hexColor);
            int r = color.R;
            int g = color.G;
            int b = color.B;
    
            // Adjust this value if you want to
            double a = 0.2; 
            return $"rgba({r}, {g}, {b}, {a})";
        }
    }
    

    In the revised code the rgbaColor calculation is now housed within a method named GetRgbaColor. This method is directly invoked in the style attribute of the MudPaper component. Consequently, the block is no longer necessary and each card’s background color is determined by its own BoxColor parameter. This ensures that each ApptCard component is styled individually, fixing the problem of all cards rendering with the last color in the loop.

    Login or Signup to reply.
  2. You could try use Guid to make each instance of component unique.
    ApptCard.razor

    @using System.Drawing
    
    <MudPaper id="@Uid" Class="pa-2 apptColor">@Text</MudPaper>
    
    <style>
        @css{
            background-color: @rgbaColor;
        }
    </style>
    
    @code {
        private string Uid { get; set; } =$"xx-{Guid.NewGuid().ToString()}";
        private string css => $"#{Uid}.apptColor";
    
        [Parameter] public string Text { get; set; } = null!;
        [Parameter] public string BoxColor { get; set; } = null!;
        private string rgbaColor;
        protected override Task OnInitializedAsync()
        {
            var color = ColorTranslator.FromHtml(BoxColor);
            int r = Convert.ToInt16(color.R);
            int g = Convert.ToInt16(color.G);
            int b = Convert.ToInt16(color.B);
            rgbaColor = string.Format("rgba({0}, {1}, {2}, {3});", r, g, b, .2);
    
            return base.OnInitializedAsync();
        }
    }
    

    Home.razor

    @page "/"
    
    @{
        var appt = new List<string> { "Blue", "Red", "Yellow" };
    }
    @foreach (var a in appt.ToList())
    {
        <AptCard BoxColor="@a" Text="@a"></AptCard>
    }
    

    Test result
    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search