razor icon indicating copy to clipboard operation
razor copied to clipboard

[Blazor] @if directive

Open mrpmorris opened this issue 2 years ago • 44 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

I'd like to be able to create markup that is nice to look at and easy for a non-programming colleague to improve the visual design of.

@if (IWantToWriteNiceCode)
{
  <ThisDoesntFloatMyBoat/>
}

This isn't nice to look at, it's quite verbose, and my non-programming colleague would undoubtedly break the logic when changing the contents to make them look good.

Describe the solution you'd like

I'd like to be able to have if and foreach directives, so my colleague only needs to know not to change any html attributes that start with an @ symbol (as is already the case).

<ThisDoesFloatMyBoat @if=IWantToWriteNiceCode/>

The preceding code is much nicer to look at, quicker to type, uses only a single line so uses less space, and easy to see what can be moved/altered without breaking things.

I would also like to be able to replace the following

@foreach(var person in People)
{
  <li>@person.Name</li>
}

With something more simple such as

 <li @foreach-person="People">@person.Name</li>

I resist giving judgement on a switch statement :)

Additional context

https://i.ibb.co/8gsnjg7/Fm68-Ngz-Xw-AA8xqv.png

mrpmorris avatar Jan 20 '23 13:01 mrpmorris

The @if directive attribute looks good to me. It has clear meaning and doesn't introduce any new difficulty.

I would recommend not getting bogged down in the @foreach attribute though. That's far weirder, declaring the name of a variable as a suffix of an attribute name. Something else like @foreach="person in People" is more obvious but it's still a bit of a mess conceptually because you might also want to refer to person in some other attribute on the element, breaking the syntactical hierarchy.

I think @if is something we could pursue as an attribute in the short term, but am not sold on other flow constructions (while, for, foreach, switch, try/catch, using, etc) having new special-case alternate syntax on top of their existing C#-style syntax.

SteveSandersonMS avatar Jan 20 '23 14:01 SteveSandersonMS

I think if and foreach are likely to be the two most commonly used constructions in .razor files. @if would be a very welcome addition, and I think a @foreach would be equally as useful.

I agree on not putting in all the other control flow.

I thought the foreach was quite intuitive as it follows the @bind directive pattern

@directive-Identifier=Source

  • @bind-Value=Source
  • @foreach-currentItem=Items

And it matches the order of foreach item in Source to make it easy to remember.

mrpmorris avatar Jan 20 '23 14:01 mrpmorris

I think this has merit. When I compare Razor template control flow with how Angular and React do it it feels like Razor is a hybrid that inherits the cons of both but not so much the pros.

Angular uses attributes, which has the benefit of keeping your html looking like html. The con is that it is essentially some kind of DSL and encourages mixing logic with your presentation.

React uses actual JavaScript control-flow statements, as you usually write html snippets inside your JavaScript files, which has the benefit of using actual programing language constructs, in an actual programing language file, to handle logic. The con is that you end up with presentation mixed in with your logic.

Razor has you wrap your HTML, inside C# code, inside HTML, in an HTML file. It feels a little awkward, to me and you basically end up with all of the cons of React and Angular... a DSL with logic mixed in presentation mixed in logic.

At the end of the day it's probably mostly a question of preference and what you're used to. For what it's worth, my preference is for something closer to Angular. Which is kind of what this issue seems to advocate for.

snowfrogdev avatar Jan 20 '23 14:01 snowfrogdev

At the end of the day it's probably mostly a question of preference and what you're used to. For what it's worth, my preference is for something closer to Angular. Which is kind of what this issue seems to advocate for.

@snowfrog I must confess to being a little influenced by Angular :) I used to use it a number of years ago and thought it was a real improvement over vanilla ASP markup that I used to write a very long time ago.

Razor syntax is certainly an improvement over vanilla ASP, but still quite similar. I think the @if @foreach approach looks more declarative rather than imperative.

Of course, we'd need <text> to support these too, otherwise we'd be forced to implement an HTML element into the result that we otherwise wouldn't want.

mrpmorris avatar Jan 20 '23 14:01 mrpmorris

@mrpmorris I understand the appeal of the solution you are proposing.

However, I do not agree with the reasoning to add something like this to Razor. You might prefer a more declarative style over a more imperative style, but that is to a large degree a matter of taste/preference.

Adding these types of constructs/primitives goes against the core philosophy or Razor, which is expressing the logic for rendering the UI directly in C#, without having to learn a new DSL. We already had this model with aspx and we moved to something like Razor for a reason.

I do not see the value of adding yet another way of doing the same thing to the language. I understand that it might appeal to some design preference or aesthetic sense, but I do not believe that there is a meaningful advantage over using the language vs having an alternative way based on a DSL.

On the contrary the drawback is that it adds two different ways of doing the same thing at a very low level.

This is something that I would say we are not likely to change, and if we do, I will think we would end up with a different language that is just not Razor anymore.

I agree with @SteveSandersonMS that we might potentially add something to conditionally render a block, but I would go as far as to say that it would not be called @if.

javiercn avatar Jan 20 '23 15:01 javiercn

@javiercn There is one very good point that you've missed.

If I give a project with .razor files to a non-programmer colleague whose job it is to make my functional UI actually look nice to users, they'll break it. I've seen it happen a number of times already, and in each case I had to spend time teaching the colleague razor programming in order to understand how to change things without breaking them.

On the other hand, when I gave them Angular apps to change I didn't have any problems at all.

Many companies have separate job positions for "full stack" programmers and UI designers. Not all UI designers know how to write code, or even want to learn.

The @if @foreach pattern follows the existing HTML paradigm, which they will already know very well.

I think limiting the discussion to what programmers want is excluding the needs of too many others.

mrpmorris avatar Jan 20 '23 15:01 mrpmorris

@javiercn

And yet we go to all the trouble to make minimal APIs to help people to get started. faster. Removing Main etc... Now we have two different ways of doing the same thing. Controllers and Minimal API. Why did we change those? Because we thought it was for the better.

I will think we would end up with a different language that is just not Razor anymore.

Maybe people want Razor to change?

My thoughts are people would vastly prefer @if over the current format. And the ones I have asked do.

And if you didn't call it @if what would you suggest?

StevenTCramer avatar Jan 20 '23 15:01 StevenTCramer

However, I do not agree with the reasoning to add something like this to Razor. You might prefer a more declarative style over a more imperative style, but that is to a large degree a matter of taste/preference.

I think this statement by @javiercn is key. This is largely about style/taste/preference and really the spirit in which razor was created. It's "smooth" integration of C# with HTML, not a DSL with C# expression constructs interleaved with HTML. This is about form, not function.

davidfowl avatar Jan 20 '23 15:01 davidfowl

@davidfowl yes it is 100% about form. But why did you make Top level statements? The Main class functioned just fine.

As a rule we try and keep code out of Razor as much as possible. We have a @code section and "code behind" to do this. I think this "form" follows along the concept of top-level statements and minimal APIs. More concise easier to work with code.

StevenTCramer avatar Jan 20 '23 15:01 StevenTCramer

Why did we change those? Because we thought it was for the better.

I think the "we" is relevant here. The framework/language designers had to agree it was a net positive. These debates are normal, and when the designers aren't fans of the "style/form" then the changes don't happen.

davidfowl avatar Jan 20 '23 15:01 davidfowl

@davidfowl See my comment regarding not everyone is a developer - https://github.com/dotnet/razor/issues/9243

mrpmorris avatar Jan 20 '23 15:01 mrpmorris

I read the comment, but my point still stands. I'm not saying I'm for one way or the other with this specific issue, but sometimes, what looks like small feature is really a paradigm shift (like this issue) and a much bigger change to the overall approach. This is the reason why this issue is being met with resistance. It doesn't fit the existing mold, it's different and as a result, the engineering team needs to spend more time understanding it and the tradeoffs etc.

That's not to say we don't change our minds, but it won't be a quick fix. Currently, we are not convinced that changing the style of razor for designers is worth introducing a new paradigm.

davidfowl avatar Jan 20 '23 15:01 davidfowl

Debates are normal and healthy. That is how we improve.

StevenTCramer avatar Jan 20 '23 15:01 StevenTCramer

@davidfowl It's more of an additional paradigm rather than a paradigm shift (which implies people must change what they already have). But it's certainly one that would make it a lot easier for non-programming visual designers to work with, so I can get on with coding Blazor instead of having to manually fit someone else's design changes into my app, or (even worse) teach programming to someone who hates it.

mrpmorris avatar Jan 20 '23 16:01 mrpmorris

1st one

@if (IWantToWriteNiceCode)
{
  <ThisDoesntFloatMyBoat/>
}

2nd one

<ThisDoesFloatMyBoat @if=IWantToWriteNiceCode/>

I don't know why but the first one is more readable and understandable than the second one for me. Maybe I have come from an ASP.NET MVC background and I am used to seeing 1st one more often than 2nd one. And am pretty sure there would be a lot of people like me who have done ASP.NET MVC development back so maybe it's the same for them as well.

And also 2nd one is just "syntactic sugar" over the first one. I don't know what is the benefit of using 2nd one instead of the straightforward 1st one.

One more thing, its easier to write code in 1st one if you have else condition; Not sure which syntax would you write for that in case of 2nd one.

1st one with else condition

@if (IWantToWriteNiceCode)
{
  <ThisDoesntFloatMyBoat/>
}
else 
{
  <SomePage />
}

ShreyasJejurkar avatar Jan 20 '23 16:01 ShreyasJejurkar

I would like to go for

@if (IWantToWriteNiceCode)
{
  <ThisDoesntFloatMyBoat/>
}

HammadMaqbool avatar Jan 20 '23 17:01 HammadMaqbool

Always wondered why we couldn't at least drop the braces if the statement body contained a single element. It could be a single line then.

@if (IWantToWriteNiceCode) <ThisDoesntFloatMyBoat/>

jimSampica avatar Jan 20 '23 22:01 jimSampica

I think it's an overall improvement.

I can understand the resistance to changing something that has been around for more than 10 years. I feel some similarities with when the razor syntax was introduced and we had to choose between ViewEngines.

Anyway, it's a very positive change. Keeping the HTML code simple is an improvement in this way. I don't agree with people saying the current way is more readable. It's difficult to follow if the code gets a bit long. That's why other frontend frameworks choose special syntaxes like these instead of adhering to the programming language features directly. And also the code formatter's job could be a lot easier than the current state of chaos we have in VS.

msynk avatar Jan 21 '23 09:01 msynk

<ThisDoesFloatMyBoat @if=IWantToWriteNiceCode/> This I would be using. Whether it would be called @if or something else. Reason - less indentations leads to better readability and the code is easier to manage. VS razor editor has still room for improvement in this regard. Interested to see but maybe users saying 'nah' are using alternative IDEs?

BieleckiLtd avatar Jan 21 '23 10:01 BieleckiLtd

Implementing this would certainly make it less awkward when writing razor compared to my vue or angular projects

gpproton avatar Jan 21 '23 11:01 gpproton

Implementing this would certainly make it less awkward when writing razor compared to my vue or angular projects

gpproton avatar Jan 21 '23 11:01 gpproton

The attributes for contidions and loops should be supported in addition to explicit blocks, as it would be a nice syntax sugar which allows to keep markup compact and in some cases - better readable. Nice idea @mrpmorris ! +1

dmitry-pavlov avatar Jan 21 '23 11:01 dmitry-pavlov

This attributes approach would help a lot for components.

ardacetinkaya avatar Jan 21 '23 11:01 ardacetinkaya

I read the comment, but my point still stands. I'm not saying I'm for one way or the other with this specific issue, but sometimes, what looks like small feature is really a paradigm shift (like this issue) and a much bigger change to the overall approach. This is the reason why this issue is being met with resistance. It doesn't fit the existing mold, it's different and as a result, the engineering team needs to spend more time understanding it and the tradeoffs etc.

That's not to say we don't change our minds, but it won't be a quick fix. Currently, we are not convinced that changing the style of razor for designers is worth introducing a new paradigm.

@davidfowl while the current approach is not bad, for individuals using other frontend framework like react, angular and vueJs this change is really good for user acquisition, i personally found writing if and for in blazor awkward in the beginning and it still awkward.

gpproton avatar Jan 21 '23 11:01 gpproton

(I'm a huge Blazor newbie but still a C#/.NET fan)

What about cases where the element takes several parameters? something like this:

<DoesThisFloatYourBoat WhenThereAreSeveralArgsA=1 WhenThereAreSeveralArgsB=2
  WhenThereAreSeveralArgsC=3 WhenThereAreSeveralArgsD=4
  WhenThereAreSeveralArgsE=5 @if=IWantToWriteNiceCode
  WhenThereAreSeveralArgsF=6 WhenThereAreSeveralArgsG=7 />

Isn't it a problem that the @if might be not very readable?

asaf92 avatar Jan 22 '23 10:01 asaf92

(I'm a huge Blazor newbie but still a C#/.NET fan)

What about cases where the element takes several parameters? something like this:

<DoesThisFloatYourBoat WhenThereAreSeveralArgsA=1 WhenThereAreSeveralArgsB=2
  WhenThereAreSeveralArgsC=3 WhenThereAreSeveralArgsD=4
  WhenThereAreSeveralArgsE=5 @if=IWantToWriteNiceCode
  WhenThereAreSeveralArgsF=6 WhenThereAreSeveralArgsG=7 />

Isn't it a problem that the @if might be not very readable?

<DoesThisFloatYourBoat @if=IWantToWriteNiceCode
                       WhenThereAreSeveralArgsA=1
                       WhenThereAreSeveralArgsB=2
                       WhenThereAreSeveralArgsC=3
                       WhenThereAreSeveralArgsD=4
                       WhenThereAreSeveralArgsE=5 
                       WhenThereAreSeveralArgsF=6
                       WhenThereAreSeveralArgsG=7 />

and also they can be colorized differently.

msynk avatar Jan 22 '23 11:01 msynk

Those who liked the @if, haven't answered the question of how else would be fit in that syntax scenario! https://github.com/dotnet/razor/issues/9243

ShreyasJejurkar avatar Jan 22 '23 12:01 ShreyasJejurkar

Those who liked the @if, haven't answered the question of how else would be fit in that syntax scenario! #46186 (comment)

Two options:

<ThisDoesFloatMyBoat @if=IWantToWriteNiceCode/>
<ThisAlsoFloatMyBoat @if=!IWantToWriteNiceCode/>

Or you could do something like Angular: https://angular.io/api/common/NgIf#showing-an-alternative-template-using-else

snowfrogdev avatar Jan 22 '23 12:01 snowfrogdev

Those who liked the @if, haven't answered the question of how else would be fit in that syntax scenario! #46186 (comment)

Two options:

<ThisDoesFloatMyBoat @if=IWantToWriteNiceCode/>
<ThisAlsoFloatMyBoat @if=!IWantToWriteNiceCode/>

Or you could do something like Angular: https://angular.io/api/common/NgIf#showing-an-alternative-template-using-else

I was expecting that already, but what is the advantage over the raw if else!?

ShreyasJejurkar avatar Jan 22 '23 13:01 ShreyasJejurkar

I was expecting that already, but what is the advantage over the raw if else!?

There are many philosophies when it comes to where structure, style and logic should be located in a web app. Depending on your philosophy of choice, you'll prefer a syntax that best fit that philosophy.

Personally, I think that html files should contain as little logic as possible. I cringe when I see stuff like

@if (SomeCondition)
{
  <div>Version 1</div>
}
else
{
  <div>Version 2</div>
}

I'd much rather have the html be something like this:

<div>@Version()</div>

With a separate .cs file working out the logic

public string Version()
{
  return SomeCondition ? "1" : "2";
}

Having the ability to write entire programs in your html using code blocks @{} has its advantages and disadvantages, depending on how you see things.

It makes it really easy to write logic inside your html, which I prefer to avoid. I like to see my html as a relatively rigid description of the structure of my presentation. I use separate code files (JS, TS, CS) that run the logic to decide which data gets fed into the structure. That data can change the content that is displayed, but also the style.

Using control flow attributes on the html element tags allow for keeping the html looking like html. It gives you the tools needed to have basic control flow while at the same time making awkward, and hopefully discourage, the heavy use of logic in your template. Which in turn, as was mentioned in another comment, will make the html easier to understand and work with for non programmer UI devs.

snowfrogdev avatar Jan 22 '23 14:01 snowfrogdev