Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a way to share a drop down inside a layout for use in all views?

I am becoming more familiar with MVC 3 and the RAZOR view engine. I have a question regarding layouts and shared controls on pages.

Let’s say I have a header section defined in my main layout. In that header is a dropdown I need to populate with project names. This dropdown will serve as a context for the entire site and is present on all pages. As an example, if the user selects “Project A” from the drop down, all of the views for the site will be based on “Project A”. Since this dropdown control is rather static and is used by the entire site, where is the best place to put the code to pull all the projects to display in the dropdown? In a Partial View? In a HTML helper? Another thought is, if a user selects a new value, they would be taken to a dashboard or similar page for that newly selected project. I am trying to figure out how to reuse this control on every page in the site without having to keep wiring it up in every possible controller.

like image 719
DDiVita Avatar asked Jul 26 '11 04:07

DDiVita


People also ask

How do I make a drop-down list in HTML?

The <select> element is used to create a drop-down list. The <select> element is most often used in a form, to collect user input. The name attribute is needed to reference the form data after the form is submitted (if you omit the name attribute, no data from the drop-down list will be submitted).

How do I bind a dropdown in MVC Razor?

How do I bind a DropDownList in MVC Razor? To populate the DropDownList in MVC using Razor, we can use multiple ways like ViewBag, ViewData, Tempdata, jQuery, Model, Database, AJAX, and Hardcoding in View.


1 Answers

You could use a child action along with the Html.Action helper. So you start by defining a view model:

public class ProjectViewModel
{
    [DisplayName("Project name")]
    public string ProjectId { get; set; }
    public IEnumerable<SelectListItem> ProjectNames { get; set; }
}

then a controller:

public class ProjectsController: Controller
{
    private readonly IProjectsRepository _repository;
    public ProjectsController(IProjectsRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index(string projectId)
    {
        var projects = _repository.GetProjects();
        var model = new ProjectViewModel
        {
            ProjectId = projectId,
            ProjectNames = projects.Select(x => new SelectListItem
            {
                Value = x.Id,
                Text = x.Name
            })
        };
        return PartialView(model);
    }
}

then the corresponding view (~/views/projects/index.cshtml):

@model ProjectViewModel

@Html.LabelFor(x => x.ProjectId)
@Html.DropDownListFor(
    x => x.ProjectId, 
    Model.ProjectNames,
    new {
        id = "projects",
        data_url = Url.Action("SomeAction", "SomeController")
    }
)

Now all that's left is to render this widget inside the _Layout.cshtml:

@Html.Action("Index", "Products", new { projectid = Request["projectId"] })

And now we could put some javascript so that when the user decides to change the selection he is redirected to some other action:

$(function() {
    $('#projects').change(function() {
        var url = $(this).data('url');
        var projectId = encodeURIComponent($(this).val());
        window.location.href = url + '?projectid=' + projectId;
    });
});

Another possibility is to put the dropdown inside an HTML form:

@model ProjectViewModel
@using (Html.BeginForm("SomeAction", "SomeController", FormMethod.Get))
{
    @Html.LabelFor(x => x.ProjectId)
    @Html.DropDownListFor(
        x => x.ProjectId, 
        Model.ProjectNames,
        new {
            id = "projects",
        }
    )
}

so that inside the javascript we don't have to worry about building urls when the selection changes and simply trigger the containing form submission:

$(function() {
    $('#projects').change(function() {
        $(this).closest('form').submit();
    });
});
like image 119
Darin Dimitrov Avatar answered Sep 24 '22 19:09

Darin Dimitrov