Open vova-lantsov-dev opened 5 years ago
Currently we don't support concatenation of strings inside the values of attributes passed to components. You can work around the issue by doing the concatenation separately and then pass in the value.
@danroth27 so you mean replace
Color="red" ... w3-@(Color) ...
With
Color="w3-red" ... @(Color) ... ?
Instead of this:
@if (Disabled) {
<button class="w3-@(Color) ... " >...</button>
}
I think you can do this:
@if (Disabled) {
var classText = "w3-" + Color + .... ;
<button class="@classText" >...</button>
}
You can also use:
@if (Disabled) {
<button class=@($"w3-{Color}")>Click me</button>
}
This is pretty important IMHO. At the moment you can't even pass an id into a NavLink helper. Strange that it used to work.
I solved it by diff way...
var link = "SomeOtherUrl/" + forecast.SomeValue;
<tr>
<td>@forecast.SomeValue</td>
<td>
<NavLink class="nav-link" href="@link">
<span class="oi oi-plus" aria-hidden="true"></span> Detail
</NavLink>
</td>
</tr>
will this problem be addressed?
Hi @burakakca. Currently this issue is on our backlog with no committed time frame to address it. So I wouldn't expect it to be addressed any time soon. In the meantime you can use the various workaround described in the earlier comments.
Just hit a similar issue today when trying to add a class conditionally.
Current work around is:
var percentageClass = "form-control";
if (!isValid)
percentageClass += " invalid";
<InputNumber
@bind-Value="@m.Percentage"
class="@percentageClass" />
... hoping to get something similar in Angular like:
<InputNumber
@bind-Value="@m.Percentage"
class="form-control"
[invalid]="@(!isValid)" />
UPDATE: I updated how I write conditional css class like so:
<InputNumber
@bind-Value="@m.Percentage"
class=@($"form-control {(isValid ? "" : "invalid")}") />
More surprising than the fact that it's been 2 years and this is STILL not fixed, is the fact that @danroth27 says that it's not coming any time soon! Don't you think this is among the most basic of features?! Any updates on this? @danroth27 @SteveSandersonMS
By what logic is something like this not allowed:
<Button Label="Delete @Product.Title" />
I know there are workarounds, but this should obviously be supported natively.
When you set a component parameter that is of type string
using an attribute, the attribute value is treated as a C# string. So, in Blazor, <Button Label="Delete @Product.Title" />
is equivalent to button.Label = "Delete @Product.Title";
in C#, which isn't what you actually wanted.
Instead you need to use C# syntax to construct the string, something like button.Label = $"Delete {Product.TItle}";
. In Razor, it get's a bit clunky to manipulate C# strings in an HTML attribute because of the quotes, but you can do something like this: <Button Label="@($"Delete {Product.TItle}")" />
, where the @()
syntax is used to clarify where the C# begins and ends.
We could still do work in the Razor compiler to make this scenario less cumbersome, but hopefully that at least give some context for what is happening.
This issue for projects that use external libraries (such as MudBlazor) makes 'dynamic styling' very pesky to implement without duplicating the component & nested content w/ @if's and @else's
(Desired code)
<MudGrid style=" width: @(condition ? "100%" : "50%" );">
@*Nested content...*@
</MudGrid>
@ud-waffle You can always do something like:
<MudGrid style="@MyGridStyle">
...
</MudGrid>
@code {
string MyGridStyle => $"width: {(condition ? "100%" : "50%" )}";
}
or
<MudGrid style="@MyGridStyle(condition)">
...
</MudGrid>
@code {
string MyGridStyle(bool condition) => $"width: {(condition ? "100%" : "50%" )}";
}
I find myself doing this sort of thing:-
<MudGrid style=@(condition ? "width:100%;" : "width:50%;")>
@*Nested content...*@
</MudGrid>
Or closer to what you started with
<MudGrid style=@($"width:{(condition ? "100%" : "50%" )};")>
@*Nested content...*@
</MudGrid>
For that case I also needed to apply other styles so I went with a different approach
<div style=" width: @(condition ? "100%" : "50%" );">
<MudGrid Style="width:100%; (...) ">
@*Nested content...*@
</MudGrid>
</div>
I also came across this issue today when trying to do the following:
<div class="@(visible ? "" : "hidden") @cssClass"
@code {
[Parameter]
public string cssClass { get; set; }
[Parameter]
public bool visible { get; set; } = true;
}
Perhaps this is because of the use of two @ symbols, but it still references the root of the issue (this post).
Is there any update on this? Seems a very common use case not currently being handled...
It's 100% still an issue.
I tried to have a variable as part of a NavLink href tag and it threw an error.
Get Outlook for Androidhttps://aka.ms/AAb9ysg
From: Vova Lantsov @.> Sent: Monday, April 25, 2022 7:16:16 PM To: dotnet/razor-compiler @.> Cc: Iain Wandless @.>; Comment @.> Subject: [dotnet/razor-compiler] Blazor RZ9986 — Component attributes do not support complex content (mixed C# and markup) (#224)
I've found that this issue was already fixed in 0.4.0 Reference 1https://github.com/aspnet/Blazor/issues/784 Reference 2https://github.com/aspnet/Blazor/issues/753
But it still present. Blazor 3.0.0-preview4 Visual Studio 2019 16.1.0 preview2 Latest vsix extension installed
Files where issue happened: Button.razorhttps://github.com/vova-lantsov-dev/bookkeeping-blazor/blob/feature-blazor-3.0.0-preview4/BookkeepingNasheDetstvo.Client/Components/ForButtons/Button.razor HalfButton.razorhttps://github.com/vova-lantsov-dev/bookkeeping-blazor/blob/feature-blazor-3.0.0-preview4/BookkeepingNasheDetstvo.Client/Components/ForButtons/HalfButton.razor
Project repositoryhttps://github.com/vova-lantsov-dev/bookkeeping-blazor/tree/feature-blazor-3.0.0-preview4
I also tried to solve this problem by deleting .vs / bin / obj directories and restarting VS.
— Reply to this email directly, view it on GitHubhttps://github.com/dotnet/razor-tooling/issues/7684, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AR3UAAP3M2GVH4XCZUHC4ZDVG3OPBANCNFSM5UJL6GKA. You are receiving this because you commented.Message ID: @.***>
I encountered this when simply trying to pass an ID into the href attribute of a NavLink component. I am surprised that this is not supported. This seems very basic. I am sure that somebody attempted to do something like this during the development of Blazor. It makes me wonder if there are other basic things that don't work as expected. I suppose I need to train more.
I encountered this error today when trying to add a class to an InputText component in an EditForm. I had a TailwindCSS class apply a red border on the InputText when it's in the Invalid state (namely the class invalid:border-red-500
), but didn't want it to be red when the InputText was empty. I did not find a better solution than simply overwriting the Tailwind class with another border color.
I had originally added a local bool, @IsInvalid
, to the class, but this caused the RZ9986 compilation error. After reading here, I added the workaround of a conditional CSS class, as proposed by @gojanpaolo, and it worked, as such:
<InputText @bind-Value="model.example" class=@($"form-control {( model.example != "" ? "invalid:border-red-500" : "invalid:border-gray-500" )} ") />
@code {
public bool
}
That only a conditional css class works is not very intuitive, and it does not seem to be a very well documented error either. Any updates on timeline for a fix for this?
Adding to this issue as I've also run into it. I think the weird thing is that e.g. a simple ternary operation works fine if it happens e.g. in a non-component tag but the same operation throws this error if it is on a component.
Example, in the following Component:
<li class="display-inline float-left nav-link @(Active ? "active" : "")">
<NavLink href="@HRef" Match="NavLinkMatch.All" class="display-block px1 py05 @(Active ? "bg-highlight" : "")">
@ChildContent
</NavLink>
</li>
//Code part omitted, Active is a bool and HRef a string
The ternary part on the li tag is valid razor but (nearly) the same ternary is invalid on a component (the NavLink in this case).
To me this feels like a weird discrepancy and I'm guessing it trips up others too.
I get this error trying to do something I thought I had done before in Blazor. I might be confusing something I did in MVC at work.
In my grid I am building, I need to know which row was just double clicked to enter edit mode. Is there a way to get the row that was double clicked? I have an int Number and Guid Id property on each row.
// if the row has columns
if (row.HasColumns)
{
<div class="@row.ClassName">
@foreach (Column column in row.Columns)
{
<div class="@column.ClassName" @ondblclick="OnDoubleClick(@row.Number)">@column.ColumnText</div>
}
</div>
<br />
}
Thanks
I figured out my issue by using a Lambda expression:
// if the row has columns
if (row.HasColumns)
{
<div class="@row.ClassName">
@foreach (Column column in row.Columns)
{
<div class="@column.ClassName" @ondblclick="() => OnDoubleClick(row)">@column.ColumnText</div>
}
</div>
<br />
}
And I had to change my edit method to accept a row.
public void OnDoubleClick(Row row)
{
// turn on EditMode
EditMode = true;
// Update the page in EditMode
Refresh();
}
Maybe this will help someone else.
I solved it by diff way...
var link = "SomeOtherUrl/" + forecast.SomeValue; <tr> <td>@forecast.SomeValue</td> <td> <NavLink class="nav-link" href="@link"> <span class="oi oi-plus" aria-hidden="true"></span> Detail </NavLink> </td> </tr>
This is working for me with "div" inside, but I need to refresh the page to make it work.
Why this f*cking artificial limitation (still) exists at all?
Something which works:
private RenderFragment Test(int a, int b, int c) => __builder =>
{
<span title="@a and @b is @c"></span>
};
Decompilation What the source-generator creates of that:
private RenderFragment Test(int a, int b, int c) => __builder =>
{
__builder.OpenElement(19, "span");
__builder.AddAttribute(20, "title", (
a
) + " and" + " " + (
b
) + " is" + " " + (
c
));
__builder.CloseElement();
};
Modified to create a component and bind to string parameter (still compiles):
private RenderFragment Test(int a, int b, int c) => __builder =>
{
__builder.OpenComponent<InputText>(19);
// BTW next line even works using AddAttribute instead of AddComponentParameter
__builder.AddComponentParameter(20, "Value", (
a
) + " and" + " " + (
b
) + " is" + " " + (
c
));
__builder.CloseComponent();
};
But writing the same using razor syntax fails artificially:
private RenderFragment Test(int a, int b, int c) => __builder =>
{
<InputText Value="@a and @b is @c"></InputText>
};
Why the razor transpiler (or what is it named exactly) has those artificial limitations? The same with abstract components: There is IComponentActivator
since net5 but it only works for hand-written code against RenderTreeBuilder - the razor transpiler just throws artificial errors for things which just work: https://github.com/dotnet/aspnetcore/pull/23607#issuecomment-1437310969
I did a workaround like @gojanpaolo. Let me know if there's a better way. One caveat to this is that I lose the Tailwind Intellisense (I come from the React world so pardon me for using a ternary inline 😛 )
class=@($"py-3 px-4 block w-full border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 {(context.IsValid(() => Location.Name) == false ? "border-red-500" : "")} disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600")
I've found that this issue was already fixed in 0.4.0 Reference 1 Reference 2
But it still present. Blazor 3.0.0-preview4 Visual Studio 2019 16.1.0 preview2 Latest vsix extension installed
Files where issue happened: Button.razor HalfButton.razor
Project repository
I also tried to solve this problem by deleting .vs / bin / obj directories and restarting VS.