I'll preface this question with, I already have the answer. But I suspect other people ran into similar scenarios and I wanted to share my solution.
Question: How can I use a switch expression in Balzor to render components?
I have a scenario where I have an object with a string property and I want to render different buttons based on the string value. Using a switch statement it looks something like this
@switch(myObject.SomeStringValue)
{
case "StringValueOne": <ButtonComponent OnClick="@DoAThing"/> break;
case "StringValueTwo": <ButtonComponent OnClick="@DoTwoThing"/> break;
case "StringValueThree": <ButtonComponent OnClick="@DoThreeThing"/> break;
default: <ButtonComponent OnClick="@DoSomethingElse"/> break;
}
My problem is I wanted to match multiple string values in each case, using pattern matching...
case is "StringValueOne" or "AnotherMatchingValue": <ButtonComponent OnClick="@DoAThing"/> break;
Based on the C# docs, I couldn't find a way to use a switch statement and pattern matching together.
Now, in general I like the syntax of switch expressions better than switch statements. I wanted to be able to use a switch expression in Blazor to get a similar outcome to the above switch statement which works natively in a razor file. How could I use a switch expression to accomplish the same goal?
CodePudding user response:
Well, here's an answer folks!
@(myObject.SomeStringValue switch
{
"StringValueOne" or "AnotherMatch" => (@<ButtonComponent OnClick="@DoAThing"/>),
"StringValueTwo" or "MatchTwo" => (@<ButtonComponent OnClick="@DoTwoThing"/>),
"StringValueThree" or "MatchThree" => (@<ButtonComponent OnClick="@DoThreeThing"/>),
_ => (@<ButtonComponent OnClick="@DoSomethingElse"/>)
})
Let me know if you find another way to do this or if this doesn't work for you.
CodePudding user response:
For simple strings, you could also just have multiple case statements like this:
@switch(myObject.SomeStringValue)
{
case "StringValueOne":
case "AnotherMatchingValue":
<ButtonComponent OnClick="@DoAThing"/>
break;
case "StringValueTwo": <ButtonComponent OnClick="@DoTwoThing"/> break;
case "StringValueThree": <ButtonComponent OnClick="@DoThreeThing"/> break;
default: <ButtonComponent OnClick="@DoSomethingElse"/> break;
}
Both StringValueOne
and AnotherMatchingValue
will result in <ButtonComponent OnClick="@DoAThing"/>
CodePudding user response:
Your code is "expensive", you're re-creating the component just to change one of the parameters - OnClick
. The sledgehammer to crack a nut!
Here's some code that demonstrates how to "switch" OnClick
based on some input. You can assign any delegate
to OnClick
that matches it's signature. Action
's are packaged delegates we can use for the purpose.
As you haven't shown ButtonComponent
I've made up a very simple one:
<button @onclick=this.ButtonClicked>Click Me</button>
@code {
[Parameter] public EventCallback Clicked { get; set; }
private void ButtonClicked()
=> Clicked.InvokeAsync();
}
Here's a test page to demo things in action:
@page "/"
<PageTitle>Index</PageTitle>
<ButtonComponent Clicked=this.buttonHandler />
<div >
<button @onclick=this.ChangeInt>Change Delegate</button>
</div>
<div >
@switcher - @this.message
</div>
@code {
private int switcher = 0;
private string message = "Nothing Clicked";
private Action buttonHandler => switcher switch
{
1 => Do1,
2 => Do2,
3 => Do3,
_ => Do0
};
private void ChangeInt()
=> switcher = switcher >= 3 ? 0 : switcher;
private void Do0()
=> message = $"Switch0 clicked";
private void Do1()
=> message = $"Switch1 clicked";
private void Do2()
=> message = $"Switch2 clicked";
private void Do3()
=> message = $"Switch3 clicked";
}