5

I have an MVC3 application with Razor and I created a View that inside renders a Partial View. This is how the main View looks like:

@{Html.RenderPartial("_SearchFilters", Model.SearchFilters);}

@* Other HTML elements *@

Inside the _SearchFilters Partial View I have the following DropDownLists inside a Form element:

Choose Year
          @Html.DropDownListFor(m => m.Year, new SelectList(Model.YearsList, "Value", "Text"), DateTime.Now.Year)

Choose Month
          @Html.DropDownListFor(m => m.Month, new SelectList(Model.MonthsList, "Value", "Text"), Model.Month.ToString(), new { @disabled = "disabled" })


       <input type="submit" value="Display" />

I would like that upon Submit the two DropDownLists keep their status, namely the value selected by the user, when the View is reloaded with the filtered data.

Is there any way to do it without using AJAX?

UPDATE

The ViewModel is as follows:

public class TableSearchFiltersViewModel
{
    public bool YTM { get;  set; }

    public int? Month { get; set; }

    public int? Year { get; set; }

    public IEnumerable<SelectListItem> YearsList
    {
        get
        {
        return Enumerable.Range(2011, (DateTime.Now.Year - 2011 + 4)).Select(m => new SelectListItem
        {
            Value = m.ToString(),
            Text = m.ToString(),
        }).OrderBy(m => m.Value);
        }
    }

    public IEnumerable<SelectListItem> MonthsList
    {
        get
        {
           return Enumerable.Empty<SelectListItem>();
        }
    }

}

Thanks

Francesco

CiccioMiami
  • 8,028
  • 32
  • 90
  • 151

4 Answers4

2

When you submit the form to the corresponding controller action, this action should take as input parameter some view model. This view model's properties will be bound from the input fields contained in the form including the selected value of the two dropdowns. Then the controller action could return the same view which will preserve the selected values of the dropdown boxes.

I would recommend you to use Editor Templates though instead of rendering partials as this will ensure proper naming of the dropdowns and eventually preserve selected values:

@Html.EditorFor(x => x.SearchFilters)
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • @Darin Dimitrov: that is clear thanks. I currently pass the view model (which is basically selectedYear and selectedMonth) to the action method on the controller and then I pass them back to the View(mainly for display to the user which year and month the dtata refer to). How can I tell to the DropDownList HTML helper that I want a default selecte value (in this case selectedYear and selectedMonth)? – CiccioMiami May 03 '11 at 09:25
  • 1
    @Francesco, if you use editor templates which name properly those dropdown lists this will be done automatically. If you don't you could specify the selected value as fourth argument to the `SelectList` constructor. – Darin Dimitrov May 03 '11 at 09:26
  • @Darin Dimitrov: I will follow your advice and create an editor template. However the problem (I thought it was not relevant) is that the DropdownList related to month is populated upon year's choice – CiccioMiami May 03 '11 at 09:30
  • @Francesco, yes indeed, cascading dropdowns. You might need to use a `MonthsList` property on your view model (the same way you did with the `YearsList`) which initially will be initialized to `Enumerable.Empty()` but in the POSTback action based on the value of the selected year you could populate the months list property. This way when you render the view the second dropdown will also have the corresponding values. – Darin Dimitrov May 03 '11 at 09:34
  • @Darin Dimitrov: As you can see from the code I posted (I omitted the javascript) my application already implements such behavior. The user selects year and month the first time (2011 and March). After the postback I can set the year DDL to selectedYear(2011) and the month DDL populates accordingly. The problem is that the month DDL displays January instead of March... – CiccioMiami May 03 '11 at 09:41
  • @Francesco, no, I don't see something like this in your code. In your code you directly use `Enumerable.Empty()` in the dropdown for the months property. Then I suppose you use javascript to implement the cascading dropdown. But as I said in my comment you need another Months collection property on your model. – Darin Dimitrov May 03 '11 at 09:43
  • @Darin Dimitrov: I updated the viewmodel as you suggested (you can see it in my updated code), I put the value selected by the user in the Month property but it does not work... – CiccioMiami May 03 '11 at 10:06
  • @Francesco, have you updated the view? Are you populating the `MonthsList` property in the POST action? Are you using Editor Templates? How does the views look like? Many question that need answers before I am amble to help. – Darin Dimitrov May 03 '11 at 11:01
  • @Darin Dimitrov: basically what I do is based on what you suggested in this answer: http://stackoverflow.com/questions/5497524/easiest-way-to-create-a-cascade-dropdown-in-asp-net-mvc-3-with-c. Thanks – CiccioMiami May 03 '11 at 11:42
1

Without ajax not, or you will have to repost the whole form. MVC is a web framework which is not dynamic like a winforms application. You will have to post the changes to your controller and reload the page with the necessary changes, or use ajax to reload these changes.

Roger Far
  • 2,178
  • 3
  • 36
  • 67
  • thanks for the answer. How would you tell to the DropDownList HTML helper that I want a default selecte value (in this case selectedYear and selectedMonth)? – CiccioMiami May 03 '11 at 09:26
  • @Francesco: As I wrote in an answer to this post - the selected value can be provided as an argument to SelectList constructor. HTH – Piotr Szmyd May 12 '11 at 00:09
1

You could provide the default values for Year and Month properties (to be selected at the first request) and bind those instead of the hardcoded startup values you provided.

So instead of:

@Html.DropDownListFor(m => m.Year, new SelectList(Model.YearsList, "Value", "Text"), DateTime.Now.Year)

Which btw seems erroneous, as selected value (which I suppose DateTime.Now.Year is in your example) should be provided as SelectList's constructor (instead of DropDownListFor method's) argument. DropDownListFor method doesn't have a 'selected value' argument.

You could write:

@Html.DropDownListFor(m => m.Year, new SelectList(Model.YearsList, "Value", "Text", Model.Year))

and analogously in the second dropdown.

This will make dropdowns keeps the selected values when rendered using the posted model (as Model.Year and Model.Month would hold those). So you should make sure those values won't get overwritten with default ones after subsequent submits.

Piotr Szmyd
  • 13,371
  • 6
  • 44
  • 61
1

I don't have IDE at this time so couldn't test but this might work:

Choose Month

EDIT:

 @Html.DropDownListFor(m => m.Month, 
Model.MonthsList.Select(
        t => new SelectListItem {
                 Text = t.Name,
                 Value = t.Value,
                 Selected = t.Value == Model.Month,
        },

 Model.Month.ToString(), new { @disabled = "disabled" })
ZeNo
  • 1,648
  • 2
  • 15
  • 28
  • thanks for your answer but it does not work. What is the x.ID field? – CiccioMiami May 13 '11 at 08:37
  • @francesco.. I edited it now it should be t.value. basically the MonthList.Select will return and IEnumerable SelectListItem and it will have selected=tru when Model.month matches with its value – ZeNo May 13 '11 at 20:11