Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I randomly add CSS attributes to Blazor component from parent layer as Vue did?

Since I want to design some reusable Blazor components, I hope they could have a feature like this:

Suppose I have a custom component "MyComponent", I could add any CSS attribute to it when I am using it:

<MyComponent Class="custom-css1 custom-css2">
    some child content...
</MyComponent>

While in MyComponent, I usually fix some common CSS attributes to the top wapper just like this:

<div class="fixed-css1 fixed-css2">
    some child content...
</div>

That means I have to combine two parts of the CSS attributes together to make the final HTML like:

<div class="fixed-css1 fixed-css2 custom-css1 custom-css2">
    some child content...
</div>

So I guess I should have this patern:

<div class="@Classes">
    some child content...
</div>

@functions
{

    [Parameter]
    private string Class { get; set; } = "";

    private string fixedClass = "fixed-css1 fixed-css2";

    private string Classes
    {
        get
        {
            return $"{fixedClass} {Class}";
        }
    }
}

To reduce redundant code, I could make a base class that have a protected Class property and every component inherent from it, but I still can't avoid writing the same combine code in each one. I hope there is some solution to add those custom CSS directly in my base class, I guess I could achieve this by override BuildRenderTree method from ComponentBase clss:

protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            base.BuildRenderTree(builder);
        }

But unfortunately, I have tried all my ways to build manually but have no idea to get it done. I don't know how to get elements of my HTML ("div" for example) and add additional CSS attributes to it.

All these are about doing a feature as Vue could easily do. In Vue code, we could certainly add any attribute to a component and pass them down to the first element in the component.

Could anybody help me complete this goal or give me some suggestion?

like image 709
SillyJumper Avatar asked Jul 05 '19 08:07

SillyJumper


People also ask

How do you add a CSS file to Blazor components?

To apply custom CSS style to a Blazor component, create a custom CSS file in your Razor page with the name of razorpage. css (i.e. Index. razor. css) and add your styles.

How do you reference a component in Blazor?

To capture a component reference in Blazor, use the @ref directive attribute. The value of the attribute should match the name of a settable field with the same type as the referenced component. When the parent component is rendered, the field is populated with the child component instance.

What is RenderFragment in Blazor?

RenderFragment is used to render components or content at run time in Blazor. The RenderFragment class allows you to create the required content or component in a dynamic manner at runtime.

How do you extend Blazor components?

Extend Syncfusion Blazor componentRight-click on the ~/Pages folder in the Visual Studio and select Add -> Razor Component to create a new Razor component (SyncButton. razor). Inherit any Syncfusion Blazor component and render your component based on your logic with Syncfusion Blazor API.


4 Answers

I think your approach is fine, it just needs a little abstraction around it to make it readable and easily managed across multiple components.

That's why I created this simple helper function library. It's exactly what you are doing in your code, but offers an API for consistency.

https://www.nuget.org/packages/BlazorComponentUtilities/

like image 136
Ed Charbeneau Avatar answered Oct 19 '22 21:10

Ed Charbeneau


try this, i have used it and it works and is simple

<div class="fixed-css1 fixed-css2 @(Class)">
    some child content...
</div>

I'm not sure if this is a bad practice,

It stops itellisense from working correctly in the class attribute,
but that is easily workable just add it last and at the end of the attribute
if you need to make changes with intellisense add a "" before the @(class), make your changes and then remove the ""

it may leave a space in the class string if the Class parameter is not set on the component
eg <div class="fixed-css1 fixed-css2 "> (space at end)

like image 29
Scott Avatar answered Oct 19 '22 21:10

Scott


As far as I know, right now, Blazor does not offer a built-in way to handle CSS, and Blazor best practices and patterns are not yet available, so you can handle CSS in whatever manner you found fit, including JSInterop.

Below is a link to a library I believe can be very useful to you: https://github.com/chanan/BlazorStyled

Hope this helps...

like image 41
enet Avatar answered Oct 19 '22 20:10

enet


You can do this in two ways.

The first way, you can use the dictionary to pass from parent to child like below. I have added the required attribute in this example.

Child Component:

<input id="firstName" @attributes="InputAttributes" />

@code {
    [Parameter]
    public Dictionary<string, object> InputAttributes { get; set; } = 
        new Dictionary<string, object>() 
        {
            { "placeholder", "Child Component Placeholder" }
        };
}

Parent Component:

<ChildComponent InputAttributes="attributesFromParent">
</ChildComponent>

@code {
    public Dictionary<string, object> attributesFromParent { get; set; } = 
        new Dictionary<string, object>() 
        {
            { "required", "required" },
            { "placeholder", "Parent Component Placeholder" }
        };
}

The second way, you can do by setting CaptureUnmatchedValues to true. and directly passing the attribute like maxlength from parent to child.

Child Component:

<input id="firstName" @attributes="InputAttributes" />

@code {
    [Parameter(CaptureUnmatchedValues = true)]
    public Dictionary<string, object> InputAttributes { get; set; } = 
        new Dictionary<string, object>() 
        {
            { "placeholder", "Child Component Placeholder" }
        };
}

Parent Component:

<ChildComponent InputAttributes="attributesFromParent" maxlength="15">
</ChildComponent>

@code {
    public Dictionary<string, object> attributesFromParent { get; set; } = 
        new Dictionary<string, object>() 
        {
            { "required", "required" },
            { "placeholder", "Parent Component Placeholder" }
        };
}

Reference: https://youtu.be/gClG243kn1o and https://www.pragimtech.com/blog/blazor/blazor-arbitrary-attributes/

like image 2
vivek nuna Avatar answered Oct 19 '22 19:10

vivek nuna