0
votes

I'm creating my first production project with Blazor WebAssembly. I'm struggle to find a way to change the view alias DOM. Basically, I have a Razor component with a form. The user can add multiple time some information.

enter image description here

In the image "Add Publication Output" is

_model.PublicationOutputs = new List<Domain.PublicationOutput>();

and when the user clicks the button I add a new item in the list

<button class="btn btn-outline-primary" type="button" 
@onclick="@(() => _model.PublicationOutputs.Add(new Domain.PublicationOutput()))">
Add Publication Output
</button>

then there is a foreach to display the new forms.

@foreach (var item in _model.PublicationOutputs)
{
    i++;

    <div class="row">
        <div class="col-2">
            <div class="form-group">
                <label class="font-weight-bold text-secondary">Stage</label>
                <p>@i</p>
            </div>
        </div>

        <div class="col">
            <div class="form-group">
                <label for="outputTypeSelect" 
                class="font-weight-bold text-secondary">
                Output type</label>
                <div class="select">
                    <select @bind="item.OutputTypeId" id="outputTypeSelect">
                        <option value="0">Select an option</option>
                        @if (_listOut != null)
                            foreach (var itm in _listOut)
                            {
                                <option value="@itm.ID">@itm.Name</option>
                            }
                    </select>
                </div>
            </div>
            <div class="form-group">
                <label for="itemShort" class="font-weight-bold text-secondary">
                Short title</label>
                <InputText @bind-Value="item.ShortDescription" 
                           class="form-control" id="itemShortDescription" />
            </div>
        </div>
    </div>
}

I think you got it. The complete result is in the following image

enter image description here

When a user selects from the "Output Type" a specific value, I want to display a div with an InputText, so he can add more details. I tried to do that in 2 ways without achieve the result.

First way was to use style and display to show or hide the div with the InputText but it doesn't work.

<div class="form-group" 
     style="@(item.OutputTypeId == 2 ? "display: ;" : "display: none;")">
    <label for="itemDetails" class="font-weight-bold text-secondary">
    Details</label>
    <InputText @bind-Value="item.Details" class="form-control" id="itemDetails" />
</div>

Then, I tried to use if

@if (item.OutputTypeId == 2) {
    <div class="form-group">
        <label for="itemDetails" class="font-weight-bold text-secondary">
        Details</label>
        <InputText @bind-Value="item.Details" 
                   class="form-control" id="itemDetails" />
    </div>
}

but again, when the select changed, the div is not displaying. If I use the same if in a label, it is working. So, when the user selects a new option from the select, the label changes the text.

<label for="itemTarget" class="font-weight-bold text-secondary" id="labelTarget">
    @(item.OutputTypeId == 3 ? "Target Journal" : "Target Congress")
</label>

How can I show/hide some div or HTML in Blazor based on the model? Plus, how can I do it with multiple instances of the same HTML based on the model?

1
Already a lot of code, do we need the "Add Publication Output" part? But we don't see how/where OutputTypeId is changed. - Henk Holterman
Yes, you are right. I have updated the post - Enrico
Also, yes, the "Add Publication Output" is where I change the select. There is one select for each block. - Enrico
You need to call StateHasChanged() after the select is changed so you'll need to use a bind on the @onchange="MyChangeCallback" event to a C# method. Using @bind is not correct here. - Cory Podojil
If I call @onchange="MyChangeCallback", how can I save the selected value in the right item? - Enrico

1 Answers

1
votes

For @if (item.OutputTypeId == 2) you have to update the the component view with StateHasChanged or better with

await InvokeAsync(StateHasChanged);

https://docs.microsoft.com/en-us/aspnet/core/blazor/components/rendering?view=aspnetcore-5.0#when-to-call-statehaschanged

For div use a show/hide variable:

 private bool ShowMyFoo   {get;set;} = false;
       private void ShowFoo()
       {
           ShowMyFoo    =   !ShowMyFoo;
       }   
for <div hidden="@ShowMyFoo">my code</p>

https://blazorfiddle.com/s/v4y8ilfm