I am trying to switch from CSS to Tailwind, a CSS framework that generates the CSS for you by typing values into the class attribute of an HTML element. One of the major problems is that when you have multiple elements with the same CSS, you end up with long and redundant classes that can be outsourced. This is a simple example:
RapportGrid.razor
<div class="grid auto-cols-fr grid-rows-auto-rows gap-y-1 gap-x-8 self-stretch my-4 border-md shadow-shadowgreybig py-[7px] px-4 @variantClass @AdditionalClasses">
@ChildContent
</div>
@code {
[Parameter] public RapportGridVariant Variant { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public string AdditionalClasses { get; set; }
private string variantClass
{
get
{
switch (Variant)
{
case RapportGridVariant.General: return "!bg-whitecolor-300";
case RapportGridVariant.Time: return "!bg-bluecolor-300";
case RapportGridVariant.Goodwill: return "!bg-redcolor-200";
case RapportGridVariant.Expenses: return "!bg-redcolor-100";
case RapportGridVariant.Booking: return "!bg-greencolor-100";
case RapportGridVariant.Sign: return "!bg-bluecolor-100";
case RapportGridVariant.Article: return "!bg-bluecolor-200";
default: return "";
}
}
}
}
Use case:
<RapportGrid Variant="RapportGridVariant.Time">
<!-- Content -->
</RapportGrid>
As you can see, this is essentially a div that wraps the content with a RenderFragment. Now I have an where the CSS has to be directly injected into the class-attribute of this element:
<input class="input-text nomargin centerInputContentVertical"
type="time"
id="startTime"
@ref="startTimeElement"
@bind-value="blazorStartTime"
@onblur="HandleStartTimeSet">
startTimeElement: for focusing the element
blazorStartTime: Type:DateTime, Validating and Triggering Events
HandleStartTimeSet: Calculating TimeSpan and setting values in other ViewModels
How can I create a variable razor-component where you can set these three values as parameters and the input is moved to the component?
I already created a component named "InputTextField.zaor" that looks like this:
<input class="transition transition-shadow duration-[40ms] ease-out border border-solid border-whitecolor-500 rounded-md bg-whitecolor-200 text-whitecolor-900 focus-visible:border-main-500 focus-visible:shadow-shadowblue @(NoMargin ? "!my-0" : "" ) @(Licence ? "!rounded-lg !py-[26px] !font-Inconsolata !text-2xl !leading-none !font-bold" : "") @(CenterInputContentVertical ? "!align-middle !flex !justify-center !itmes-center" : "") @AdditionalClasses"
type="time"
id="startTime">
@code {
[Parameter] public string AdditionalClasses { get; set; }
[Parameter] public bool NoMargin { get; set; }
[Parameter] public bool Licence { get; set; }
[Parameter] public bool CenterInputContentVertical { get; set; }
}
I also tried attribute splatting, inserting attributes via a dictionary & passing the values via Parameters.
Nothing worked as intended for me and I’ve already invested way too many hours to solve this. I hope someone can help me out with my issue 🙂
2
Answers
I've done some research and came to this solution. I think you can still make some code-cleanup and simplifiy the component. But at this state I'm pretty satisfied with my solution:
InputField.razor
Sample Use-Case
I know that there are multiple uncertainties why I did it in this way. To clarify that, I need to explain every single purpose of each variable which will go beyond the scope^^
Update
On clarifcation in the comments here’s a version of your component with the binding set up and the ref. Note that this is set up for the
TimeOnly
type as that is the Input type. You may need to adjust this. I haven’t complicated the control by setting up different typing as you have commented about your experience level in the comment. I’ve also added code to help set up first focus as that’s possibly why you are using element.And demo code:
This is the original answer
I’m not quite sure which three parameters, so if I’m wrong in my assumptions of your intent please tell me. I’m happy to clarify anything. 🙂
On the Css you can create a
CSSBuilder
class [at the bottom of this answer] that constructs the Css in a more structured way. For example:You’ll find several different implementations of this if your search around. you can extent it’s functionality to fit your specific needs.
On building complex input type components, there’s a recent question and answer here that demonstrates some different approaches.
How do I pass a @bind-Value to a child component?.