Dortimer
Dortimer

Reputation: 617

Show/Hide elements based on changing value in the Model

Essentially, I have a view that could be broken down into 3 parts. At the top is a drop-down option that -based on its value, determines if the second or third parts should be displayed.

The drop-down is generated with @Html.EnumDropDownListFor(m => m.SomeType). The values will be something like TypeA TypeB TypeC. I have two divs I need to hide based on the selected value. If it's TypeA it'll show one div, TypeB will show the other, and then TypeC shows both of those divs.

I have a few different things I've tried, but this is a dumbed down snippet of what I'm working with, but I think it should be enough to address the specific issue.

@model MVC_Proj.Models.SomeViewModel
@{
}

<div>

    @if(Model.SomeType == TypeA || Model.SomeType == TypeC)
    {
        <div>
            Showing first block
        </div>
    }

    @if(Model.SomeType == TypeB || Model.SomeType == TypeC)
    {
        <div>
            Showing second block
        </div>
    }

</div>

One thing I'm wondering about is the behavior of @if() statements in razor views. Is this something that is just looked at when it 'compiles' and serves the view? Or can it potentially be molded to work dynamically and reflect the changing value? Alternatively, is there another 'built-in' way to handle this, or am I going to have to go with jQuery or the like?

(I did look this over, but I wasn't able to get it working for my situation How to hide a div element depending on Model value? MVC)

Upvotes: 1

Views: 854

Answers (2)

cvillalobosm
cvillalobosm

Reputation: 155

Following previous response, here I post an example of how you can do it:

    $.post("yourcontroler/LoadSections", AddAntiForgeryToken({ typeId: selectedType }),
    function (response) {
        $(".types-container").html(response);
    }).done(function () {});

*Ignore the "AddAntiForgeryToken" method if you don't need that, that is just something for security I use for my Post requests sent with Ajax.

The response added in the container with ".html(response)" is because the controller will send back a partial view that contains the proper generated HTML already processed with the conditions you mentioned. As user1538301 mentioned, the decision according to the user's selection must be processed in the server side so the view can "change" and show the sections accordingly.

Here is an example of the code in server-side:

    public ActionResult LoadSections(string typeId)
    {
        var model = this.LogicService.ProcessSelectedType(productId).Result;

        return PartialView("_Sections", model);
    }

And now the PartialView will receive the model with the property value that helps to decide which section will be shown:

    @model Project.ViewModels.Sections.SectionsViewModel

    @if (string.IsNullOrEmpty(Model.TypeId) && Model.TypeId == "TypeA")
    {
       <div class="row ml-0">
         <p class="w-110px">Here I show the TypeA section</p>
         <div class="TypeA">
            // TypeA content goes here
         </div>
       </div>
    }
    @else if (string.IsNullOrEmpty(Model.TypeId) && Model.TypeId == "TypeB")
    {
        <div class="row ml-0">
        <p class="w-110px">Here I show the TypeA section</p>
          <div class="TypeA">
            // TypeB content goes here
          </div>
       </div>
    }

I hope this can give you an idea on how you can implement what you need.

The other option you have is to manipulate each section container showing / hiding depending on the user's selection. However, I will recommend the first option.

regards,

Upvotes: 1

gabriel.hayes
gabriel.hayes

Reputation: 2313

You wouldn't be able to dynamically update a RazorPage without JavaScript, those values are only evaluated server-side at render time.

You'll need to use AJAX and JavaScript to dynamically update the page based on changing values from the server.

Upvotes: 2

Related Questions