2

I have an application with 50 different lookup/dropdowns which an administrator will need to manage...and it must look like the initial image below.

I am unsure if this is a good way to do this...but my general thought is to have a partial for each lookup & dynamically render the correct partial when the user clicks on the Lookup Name (to the left).

I am trying to avoid...

  • Creating 50 different Controllers
  • Creating 50 different Actions
  • Creating 50 different Views

MY QUESTIONS:

Q: How do I load different partials from a single view?
Q: Is this even the right approach for this problem?
Q: Is there a better way to do this?

THE SCREEN:
The screen would look something like this...

enter image description here

THE CONTROLLER:

public class LookupsController : Controller
{
    // GET: administration/lookups
    [HttpGet]
    [AllowAnonymous]
    public ActionResult Index()
    {
        // (1) Simply return the 1st LOOKUP's PARTIAL

        // How?
        return View();
    }

    // GET: administration/lookups/{name}
    [HttpGet]
    [AllowAnonymous]
    public ActionResult Index(string name)
    {
        // (1) If the NAME doesnt map to a LOOKUP PARTIAL = Exception

        // How?    
        return View();
    }
}

THE SOLUTION:
There may be a better way to do this...but this is the general idea

enter image description here

Prisoner ZERO
  • 13,848
  • 21
  • 92
  • 137
  • I don't know if I got it right, but let me try to understand. Is the database table going to be shared for each one of the lookups? Because if it is, you can maybe create a Type for the lookups, then you would have a Type for Areas, Locations, Products and so on... And then you shouldn't have to create a different actions and view for each lookup. – Ana Carolina Manzan Jun 18 '17 at 17:33
  • There is no database table shown here – Prisoner ZERO Jun 18 '17 at 19:18
  • @PrisonerZERO I think "dynamically render the correct partial when the user clicks on the Lookup Name" using ajax is a good idea. In that case you will have to create multiple Actions (no need different controllers) and return different partials and set View html on return from those actions. Its a good idea to create different actions as ur actions then would be reusable elsewhere. – User3250 Jun 19 '17 at 04:06

1 Answers1

0

Here is what I did in Proof-of-Concept (POC) form...and it works. I will wait to mark this as the answer in case someone comes-up with a better idea.

In my particular case, I don't need the View Model to be Strongly Typed to the Lookup's underlying Entity...as I am calling a Web API after rendering. However, in case it helps folks...I am showing the PartialModel property here anyhow.

  • I am posting this as-is in case someone needs it
  • I will update the CSS later

THE CONTROLLER:

public class LookupsController : Controller
{
    // GET: administration/lookups/{name}
    [HttpGet]
    [AllowAnonymous]
    public ActionResult Index(string name)
    {
        var viewModel = new LookupsIndexViewModel(name);

        return View("index", viewModel);
    }
}

THE VIEW MODEL:

public class LookupsIndexViewModel
{
    #region <Properties>

    private const string DEFAULT_PARTIAL_PATH = "~/Areas/Administration/Views/Lookups/Partials/ProductsPartial.cshtml";

    #endregion

    #region <Properties>

    public String PartialRelativePath { get; set; }
    public PartialViewModel PartialModel { get; set; }

    #endregion

    #region <Constructors>

    public LookupsIndexViewModel(string name)
    {
        Init(name);
    }

    #endregion

    #region <Methods>

    public void Init(string name)
    {
        PartialRelativePath = DEFAULT_PARTIAL_PATH;

        // TODO: Use a factory here
        if (!string.IsNullOrWhiteSpace(name))
            SetPartialProperties(name);
    }

    ///<note>You could certainly replace this functionality with a Factory object</note>
    private void SetPartialProperties(string name)
    {
        string root = "~/Areas/Administration/Views/Lookups/Partials/";

        switch (name.ToLower())
        {
            case "andsoon":
                PartialRelativePath = root + "AndSoOnPartial.cshtml";
                PartialModel = new PartialViewModel();
                break;

            case "areas":
                PartialRelativePath = root + "AreasPartial.cshtml";
                PartialModel = new PartialViewModel();
                break;

            case "locations":
                PartialRelativePath = root + "LocationsPartial.cshtml";
                PartialModel = new PartialViewModel();
                break;

            case "products":
                PartialRelativePath = root + "ProductsPartial.cshtml";
                PartialModel = new PartialViewModel();
                break;

            case "someotherthing":
                PartialRelativePath = root + "SomeOtherThingPartial.cshtml";
                PartialModel = new PartialViewModel();
                break;

            case "storageyards":
                PartialRelativePath = root + "StorageYardsPartial.cshtml";
                PartialModel = new PartialViewModel();
                break;

            case "yetanotherthing":
                PartialRelativePath = root + "YetAnotherThingPartial.cshtml";
                PartialModel = new PartialViewModel();
                break;
        }
    }

    #endregion
}

public class PartialViewModel
{
    // Your awesome Strongly Typed View Model stuff goes here
}

THE VIEW:

@using Web.Areas.Administration.ViewModels
@model LookupsIndexViewModel

<div class="container">
    <div class="row">
        <div class="col-md-12">
            <h1>Lookups Administration</h1>
            <h2 id="subTitle"></h2>
        </div>
    </div>
    <div class="row">
        <div class="col-md-3">
            <!-- Sections Menu-->
            <ul class="nav nav-section-menu mb-4 py-3">
                <li>
                    @Html.ActionLink("Areas", "index", "lookups", new { area = "Administration", name = "areas" }, null)
                </li>
                <li>
                    @Html.ActionLink("Locations", "index", "lookups", new { area = "Administration", name = "locations" }, null)
                </li>
                <li>
                    @Html.ActionLink("Products", "index", "lookups", new { area = "Administration", name = "products" }, null)
                </li>
                <li>
                    @Html.ActionLink("Storage Yards", "index", "lookups", new { area = "Administration", name = "storageyards" }, null)
                </li>
                <li>
                    @Html.ActionLink("Some Other Thing", "index", "lookups", new { area = "Administration", name = "someotherthing" }, null)
                </li>
                <li>
                    @Html.ActionLink("Yet Another Thing", "index", "lookups", new { area = "Administration", name = "yetanotherthing" }, null)
                </li>
                <li>
                    @Html.ActionLink("And So On", "index", "lookups", new { area = "Administration", name = "andsoon" }, null)
                </li>
            </ul>
        </div>
        <div class="col-md-9">
            @Html.Partial(Model.PartialRelativePath, Model.PartialModel)
        </div>
    </div>
</div>

@section scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
            onReady();
        });
    </script>    
}

EACH PARTIAL:

<div id="grid"></div>

<script type="text/javascript" defer>

    // RESEARCH:
    // https://stackoverflow.com/questions/7556400/injecting-content-into-specific-sections-from-a-partial-view-asp-net-mvc-3-with

    var onReady = function ()
    {
        $("#subTitle").text("And So On");

        $("#grid").kendoGrid({
            dataSource: {
                type: "odata",
                transport: {
                    read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Customers"
                },
                pageSize: 20
            },
            height: 550,
            groupable: true,
            sortable: true,
            pageable: {
                refresh: true,
                pageSizes: true,
                buttonCount: 5
            },
            columns: [{
                template: "<div class='customer-photo'" +
                "style='background-image: url(../content/web/Customers/#:data.CustomerID#.jpg);'></div>" +
                "<div class='customer-name'>#: ContactName #</div>",
                field: "ContactName",
                title: "Contact Name",
                width: 240
            }, {
                field: "ContactTitle",
                title: "Contact Title"
            }, {
                field: "CompanyName",
                title: "Company Name"
            }, {
                field: "Country",
                width: 150
            }]
        });
    }
</script>
Prisoner ZERO
  • 13,848
  • 21
  • 92
  • 137