3

I'm working with Blazor after a long time doing react, and I'm really not understanding how (as far as I can tell) Blazor has very limited ability to compose HTML results dynamically in the code. For a simple example, I have a user profile and I want to show an icon / badge to demonstrate the inactive status of the user. What's the "right" way to do this? I have something like this (in pseudo code since I can't seem to get the interpreter to accept my attempts):

@(UserViewModel.IsInactive == true ? "<i class=\"ps-2 fas fa-seal-exclamation\" style=\"color: yellow\" title=\"Inactive\"></i>" : "")

This just returns the actual HTML however, it doesn't render it.

Another similar situation I'm seeing a lot is conditionally displaying a line of text, like if the address exists, display it but otherwise don't show the line:

@(UserViewModel.Address?.Address1 ? UserViewModel.Address.Address1 + "<br/>" : "")

This works but seems a little awkward-- is it possible to do a function in the code-behind C# page (MyComponent.blazor.cs) that would just return the rendered HTML? If it is possible I haven't found the right return type for it, and it always errors out. In react I would compose many little helper functions to return HTML based on a parameter or object passed in-- I don't see how to do that in Blazor.

user101289
  • 9,888
  • 15
  • 81
  • 148
  • 1
    Blazor 0.5.0 added the ability to render a raw string as HTML, more [here](https://stackoverflow.com/q/50604366/9363973). Basically just cast your string to a `MarkupString` like `@UserViewModel.IsInactive ? (MarkupString) " – MindSwipe Apr 06 '22 at 15:08
  • 2
    It's better to *not* use such code even if it's possible. You lose the ability to edit and check the HTML code and maintenance simply becomes harder. One could even say it's better to use and change the value of the `display` attribute, setting it to `none` if the field is `Inactive`. This way the DOM wouldn't change if the model changed. Better yet, you could *bind* it to a component field, controlling `display` through Blazor's binding – Panagiotis Kanavos Apr 06 '22 at 15:10
  • I totally agree with Panagiotis Kanavos said, however there are times where doing this may be better, but in your case, don't do it – MindSwipe Apr 06 '22 at 15:14
  • so is the consensus of blazor devs to accept having big control blocks and display logic scattered throughout the view code? Maybe I'm just not used to it, but it seems very hard to read and just messy. – user101289 Apr 06 '22 at 15:16
  • Not at all. What you try to do is having the same big control blocks in a single line, with an extra rendering step. That's frowned upon in all web frameworks and styles. What's wrong with just `..` ? Set `_inactiveDisplay` to `none` and nothing is displayed. Set it to `block` and the element appears. Blazor is React#, not client-side PHP - even though PHP good practices frown upon string concatenations like this for at least a decade. – Panagiotis Kanavos Apr 06 '22 at 15:17

1 Answers1

6

Try this

@if(UserViewModel.IsInactive)
{
    <i class="ps-2 fas fa-seal-exclamation" style="color: yellow" title="Inactive"> 
    </i>
}
Caius Jard
  • 72,509
  • 5
  • 49
  • 80
Surinder Singh
  • 1,165
  • 1
  • 3
  • 11
  • Yeah, I'm aware of that syntax, but was hoping I could do this as a ternary statement because otherwise the blazor component becomes a messy trainwreck of if statements, and VS Code / VS / Rider don't seem to know how to format it. – user101289 Apr 06 '22 at 15:13
  • 2
    @user101289 why do you want that? There are a lot of downsides for no benefit. Harder to write, harder to maintain, Blazor has no idea what elements may need to be displayed so it has to make significant changes each time the property changes. – Panagiotis Kanavos Apr 06 '22 at 15:14
  • @user101289 I fail to see how this is less concise than your attempt. If you really wanted, you can get rid of the extra newlines and consolidate it onto a single line. Which, in fact, would be shorter than your original code. (and more clear) – Kirk Woll Apr 06 '22 at 15:38