Pre-populate ListBox / MultiSelectList with selected items - asp.net-mvc

Is there a way to pre-populate a MultiSelectList with selected items?
Example:
I have a single View that has the following ListBoxFor that will cause the page to update what it's displaying by allowing filtering of Model.Companies.
#Html.ListBoxFor(m => m.SelectedCompanies, new MultiSelectList(Model.Companies, "IdString", "CompanyName")
What I'd like to have happen is after the update, the MultiSelectList will have the items that were selected before the page updated and refreshed. Does that mean I need to return SelectedCompanies with what was selected, or is there another way?
I am using the javascript library Chosen for usability of the ListBox on the client side, but I don't think that this affects what I'm trying to do.

Sometimes, JS libaries can interfere with your desired results. I can't speak for Chosen JS library, but inspect the markup and see how it renders. As long as it still has the listbox on the client (it must have some input element defined somewhere; my guess it hides it and updates the values as they are selected), then yes it should integrate fine.
However, when the controller posts back, you have to repopulate the Model.SelectedCompanies property with whatever values came back from the POST operation to the controller. The property should still have the selected companies if you return a View from the POST operation. If you are using a RedirectToAction instead, you'd have to store the selections in TempData.

Related

How to handle different post sources in Asp.NET MVC with a strongly typed view

Say I have a model that maps a person and I want to build a view for this model having some text inputs and a series of drop-downs to select state, province, city.
I'm adding #onchange = "this.form.submit()" in each #Html.DropDownListFor to post back to the server and drill-down the selection on those drop-downs.
How can I understand in my controller the source of said post? How do I distinguish the post coming from a drop-down change to the one coming from a submit button?
While not being able to understand the exact source of the postback, based on this question and answers I'm at least able to check if the source was one of the submit buttons by simply checking:
if(Request.Form["submitButtonNameAttribute"] != null)
When multiple buttons are available, only the clicked one is != null at postback.
Still, this is not a complete solution related to the original answer, but while a button may indicate an action to be run, other changes in the view may just invoke some sync work on the model.

MVC checkbox checked state issue

Good morning,
I have a view that display's search results for customers. On top of the view i have a filter that has a few checkboxes. The user can select multiple checkbox items and press the filter results button. When the user presses the button it calls an action that filters the result. The page is also refreshed. My question now, how can i make the page remember what checkboxes are checked. Because when the results are returned the filter elements are reset.
Thanks in advance.
you can use TempData. TempData VS ViewBag VS ViewData
you used ViewData, After the redirect, the ViewBag & ViewData objects are no longer available
TempData is also a dictionary derived from TempDataDictionary class
and stored in short lives session and it is a string key and object
value. The difference is that the life cycle of the object. TempData
keep the information for the time of an HTTP Request. This mean only
from one page to another. This also work with a 302/303 redirection
because it’s in the same HTTP Request. Helps to maintain data when you
move from one controller to other controller or from one action to
other action. In other words when you redirect, “Tempdata” helps to
maintain data between those redirects. It internally uses session
variables. Temp data use during the current and subsequent request
only means it is use when you are sure that next request will be
redirecting to next view. It requires typecasting for complex data
type and check for null values to avoid error. generally used to store
only one time messages like error messages, validation messages.
TempData["CheckedList"] = YourCheckBoxListValues; //in your controller
in your View
#{
var tempchkboxList = TempData["CheckedList"] as yourStronglyTypeClass;
//or
var tempchkboxList = TempData["CheckedList"].ToString();
}
Depends on how long the input criteria should be remembered.
You could also save it in your session via Session["customerCriteria"] = yourCriteria, but it would be easier to give an example if you had provided some code.
You can keep your selected/checked checkbox details in session variable when you post the form (by clicking on the search button). In the HttpPost action,read the checkboxes which were checked and add that to a collection property of your viewmodel and send it back to the view. set the session variable values to null once you are done with it (after reading). in the view, use your viewmodel value to set the checked status of those checkboxes.
Another option is using ajax. When you click on search.Read your search criteria and make an ajax request to the action method. Return a partial view back and update only the div/table which shows the results of the search.

How to preserve text during a postback with ASP.NET MVC 3

I have a Product edit screen. The user can select a Vendor for the Product. To do this, I display a jQueryUI dialog box which allows them to browse for and select a Vendor. When the user selects the Vendor, I update a hidden VendorID input on the page, which is part of my page's model. I also update several divs with details about the Vendor they have selected. These are for display purposes only--only the id is needed to persist the selected Vendor.
This all works fine and dandy except when there is an error on postback, in which case I redisplay the same view. ModelState takes care of preserving all my form fields (including the hidden VendorID). However, my divs with the Vendor text are (of course) empty since they're not posted to the server.
I first went down the path of creating hidden fields for each of my Vendor display fields and putting them on the model. Then the hidden fields survive the postback, but that doesn't solve the problem of actually redisplaying the text on the screen.
The three options I can think of are:
On postback, if there is an error, go to the database, fetch the Vendor using the supplied VendorID and re-populate the model with the text I want to display.
Use RenderAction and have an action which renders the details of the selected Vendor.
Use readonly textboxes instead of divs to display the Vendor details.
None of these feel very satisfactory to me. I feel like I might be missing an obvious solution. Are there any better solutions?
I would suggest you not have the extra Vendor information come down as part of the main page. Create a javascript function showVendorInfo(). When called, if the VendorID hidden input has a value, it gets the relevant Vendor information via AJAX and displays it, using an AjaxGetVendorInfo action method. Call this function from two places:
In document.ready()
after a Vendor is selected with jQueryUI display.
Now, this would be in an action method. You could, if you expect your users to have latency issues, do the following to avoid some ajax calls: In the view check if you know the VendorID; if so, call Html.RenderAction call the same AjaxGetVendorInfo action method from the view.
A bonus to this is that it avoids what I have found to be a big no-no: Including both display-only values and model-binding values in your ViewModel. This makes for a very confusing ViewModel, especially when there are validation errors. [Getting on soap box] It's best to have your ViewModel to just have properties intended for modelbinding, for your state. Put list values, extra display information, etc., into ViewData or have them show up via AJAX.

Maintain state of a dynamic list of checkboxes in ASP.NET MVC

I have a class called "PropertyFeature" which simply contains PropertyFeatureID and Description. It's a proper model created through LINQ to SQL mapped to an SQL Server database table. An example instance/row would be:
PropertyFeatureID: 2
Description: "Swimming Pool"
The number of rows (PropertyFeatures) can of course grow and shrink, and so I want to dynamically render a list of checkboxes so that the user can select any of them.
I can dynamically render the Checkboxes easily enough, with something like:
<%foreach (var Feature in (ViewData["Features"] as IEnumerable<MySolution.Models.PropertyFeature>)) { %>
<%=Html.CheckBox("Features", new { #id = Feature.PropertyFeatureID, #value = Feature.PropertyFeatureID })%><label for="Feature<%=Feature.PropertyFeatureID%>"><%=Feature.Description%></label>
<%}%>
I specify the ID for each checkbox and render the matching label so that the user can intuitively click the label and toggle the checkbox - that works great.
I set the CheckBox's "name" to "Features" so all the checkboxes render with the same name, and the MVC Model Binder piles them into a single collection called "Features" when the form is posted. This works nicely.
Once the form is submitted, I use the checked values and store them, so I need the actual integer values so I know which PropertyFeature is selected, not just a pile of Booleans and field names. So ideally, I want it as an array or a collection that's easy to work with.
I am able to retrieve the selected values from within my Controller method when the button is clicked because I have specified the parameter as int[] Features.
But the problem is that it doesn't maintain state. That is, when I click the submit button and the page reloads (with the form again displayed) I want all of the dynamic checkboxes to retain their checked status (or not). All of the other fields that I've created with Html.DropDownList and Html.TextBox all maintain their states successfully no problems at all on the same page in the same form.
I have spent hours reading all of the other threads and articles on similar issues and there is a lot of talk about using ICollection and IDictionary to bundle things up and include a Boolean value for each item so that it can maintain the checkbox state. But I don't 100% grasp how to use that in the context of my own personal example. I would like to keep the solution really simple and not have to code up pages of new classes just to maintain my checkbox state.
What is the cleanest and proper way to do this?
I got it working after much playing around with the various different approaches.
In the view:
<%string[] PostFeatures = Request.Form.GetValues("Features");%>
<% foreach (var Feature in (ViewData["AllPropertyFeatures"] as
IEnumerable<MySolution.Models.PropertyFeature>))
{ %>
<input type="checkbox" name="Features"
id="Feature<%=Feature.PropertyFeatureID.ToString()%>"
value="<%=Feature.PropertyFeatureID%>"
<%if(PostFeatures!=null)
{
if(PostFeatures.Contains(Feature.PropertyFeatureID.ToString()))
{
Response.Write("checked=\"checked\"");
}
}
%> />
<label for="Feature<%=Feature.PropertyFeatureID%>">
<%=Feature.Description%></label> <%
} %>
In the receiving controller method:
public ActionResult SearchResults(int[] Features)
This method has a number of advantages:
Allows labels to be clicked to toggle the corresponding checkboxes (usability).
Allows the Controller method to receive a super tidy array of ints, which ONLY contains the ints that have been selected - and not a whole other pile of items which were unselected or containing false/null/blank/0 etc.
Retains the checkbox's checked state when the page reloads containing the form, i.e. the user's selection is retained.
No random/stray type=hidden input fields created from the default ASP.Net MVC Html.CheckBox helper - I know it does those for a good reason, but in this instance, I don't require them as I only want to know about which IDs have been selected and for those to be in a single, tidy int[].
No masses of additional server side bloated classes, helpers and other happy mess required to achieve such a simple thing.
I would recommend this approach for anyone wanting the cleanest / bloat-free solution for a dynamic checkbox list where you need the IDs and you just want to get down to business!
The problem is that when you are rendering your list of checkboxes, you aren't setting any of them as selected. You will need to set your int[] Features in ViewData, and then in your foreach loop, check to see if the ID of that Feature is in the array in ViewData.
something like:
<%=Html.CheckBox("Features",
((int[])ViewData["SelectedFeatures"]).Contains(Feature.PropertyFeatureID),
new { #id = Feature.PropertyFeatureID, #value = Feature.PropertyFeatureID })%
although I didn't test it, so it might not be 100%.

How to get the selected value of a dropdown in the MVC View itself

I have a drop down in a MVC View, which is some thing like this:
Html.DropDownList(id, Range(0,10)
.Select(x => new SelectListItem {Text = x, Value = x}))
In the view itself, I need the selected value of this drop down. I know that I can access that in a JavaScript, but I am looking for a way to get it in the view itself from the drop down properties or something like that.
How can I access it? I tried to figure out some thing from intellisense but nothing relavant showed up, help is much appreciated.
Edit: I want the value after a few lines after the declaration of the drop down, I know that I can access it from JavaScript and by posting the form, Is there noway to access it on the view itself ?
Edit2: If its not possible to access it in view, please explain the reason, I am more interested in knowing it.
Thanks.
After reading at your question, it sounds like you want to have the drop down list supply a value for a lower section of the same page.
First and foremost, you will need to place the DropDownList within a form construct, as in:
<% using (Html.BeginForm("ProcessValue", "ThisPage")) { %>
<%= Html.DropDownList("DropID", Range(0, 10).Select(a=>new SelectListItem { Text = x, Value = x }) %>
<input type=submit value="Submit" />
<% } %>
You need to set up a few things ahead of time:
You have to have a submit button, or a similar construct, in order to retrieve the value of the DropID variable.
You need to set up an controller method that will handle the processing of the value, then redirect back to the original page with the selected value in the page's ViewData.
Finally, you need to set up the view so that the post-processing section will only display if you have a valid value in the DropID variable.
It's not as simple as just placing a DropDownList in a view and then using that value later on in the page. You have to get the controller involved to manage the data transport and you have to set up the single view to handle multiple states (ie. before the value is selected and after the selection takes place).
To get the selected value you could use either javascript or a controller action to which the form containing the select box is submitted.
The selected value will be in the FormCollection or QueryString collection with the name of the DropDown's ID in the controller action that receives the form submission from this view. You can either submit the values with a classic POST or GET or via AJAX, but you have to wire up a server-side action that processes that input.
There is a SelectList class as well wich allows you to define wich item will be selected.. and knowing that - you will know selected value..
Also.. if no value is selected explicitly, dropdowns tend to select the first item in the list.

Resources