I am using MVC and I would like to have two dropdowns where ones values are dependent on another. Additionally based on the combination on the two dropdowns saved the corresponding ID.
I have a code table that consists of
I would like to have dropdown one be a list of Manufacturers then based off the selection I would like dropdown two to be any models that have that as a Manufacturer. Then when I save the record that these dropdowns are used for I would like to record the ManufacturerModelID that is assigned to that combination. Is this possible?
If I understood well, you want to apply the MVC model to your application.
If yes, there is not a matter of "if", you can implement anything. You just need to separate your model from your view and controller.
In your case, I would go for "object oriented" javascript. Having separated the Models in Objects helps understanding the MVC itself.
Programming everything under a namespace like "MANUFACTUREAPP" would be helpful too.
1)For the Model
a) You need to have an object "Manufacturer" with fields like this.id, this.description, this.models = []. Then you need the setters, getters and your magic function that would push to this.models the models it has. So in the end just one more function like getManufacturer() that will get you an object filled with eeeverything this manufacturer has.
b) You need a "ManufacturerModel" with this.model, this.modelDescription, this.manufacturerID = [], setters, getters, init and all your funky functions.
2) For the View
a) You need your "View" object with functions like:
onManufacturerClick = function(){
manufacturersModels = MANUFACTUREAPP.manufacturers.getMeWhatIwant(howIwantIt);
}
So now you can be proud that your app supports the MVC architecture.
3) For the controller just follow the same concept.
In your main you want to create your object in your init function like:
init = function(){
MANUFACTUREAPP.manufacturers = new MANUFACTUREAPP.init();
}
Two friendly advices. Study the MVC in theory because it might get tricky if you didn't understood it 100%. And my best advice would be...grab a pen and draw your models before if you want to save tiiiime and energy!
EDIT
just noticed the asp.net tag.. Anyway, I am gonna leave that here. I am not familiar with asp.net but I guess the theory should be the same..
You can do it using jQuery and ajax.
Assuming your razor view renders the markup like this.
<select name="Manufacturer" id="Manufacturer">
<option value="1">Aaaaa</option>
<option value="2">Bbbbb</option>
<option value="3">Ccccc</option>
</select>
<select name="Model" id="Model">
</select>
Now have this javascript in your page, which listens to the change event of the first select element and get the value of the selected option and send it to your server using ajax. Let your server action method returns the models belongs to the manufacturer id.
$(function(){
var urlForModesl = "/Manufacturer/Models";
$("#Manufacturer").change(function(){
var manufacturerId= $(this).val();
$.getJSON(urlForModesl,function(data){
var modelsHtml="";
$.each(data,function(a,b){
modelsHtml+="<option value='"+b.Id+"'>"+b.Name+"</option>";
});
$("#Model").html(modelsHtml);
});
});
});
Assuming your Models action method returns a list of objects with Id and Name property in JSON format.
public ActionResult Models(int id)
{
var list= db.ModelManufactors.Where(s=>s.ManufacturerId==id)
.AsEnumerable()
.Select(s=> new { Id=s.ManufacturerModelId, Name=s.Name}).ToList();
return Json(list,JsonRequestBehaviour.AllowGet);
}
Related
I have a Razor view in my asp.net MVC3 application with a dropdownlist like this:
#Html.DropDownListFor(model => model.Account.AccountType, new SelectList(Model.AccountTypes, "AccountTypeCode", "Abbreviation"))
This dropdown is inside a form. When form is posted to action method and viewmodel is filled because of model binding, It get the value(AccountTypeCode) and not the text "Abbreviation" property of dropdownlist. I want to get both of these. how can I get these in post action method.
Please suggest.
If you need more than one property of an object as a value for a dropdown, the easiest way is to create a combination of these in a partial class
EF 4, how to add partial classes this quesion should help you. You will be able to combine values under one property that you will provide to your dropdown helper.
If you don't want to use partial classes I would advise creating your own helper, that will be a lot easier than trying to use something that does not fit your needs. You can do something like :
#helper CustomDropdown(string name, IEnumerable<AccountTypes> valueList)
{
<select>
#foreach (var item in valueList)
{
<option value="#item.Abbreviation #AccountTypeCode">#item.Abbreviation</option>
}
</select>
}
Google "Creating an Inline HTML Helper" to get some valuable resources on that topic
I struggled with this recently, and the best I could do was:
ViewBag.Message = myModel.myProperty.ToString().
in the controller action. Assuming myProperty is AccountType.
Then in my view I just did
#ViewBag.Message
The next problem I encountered is that it spit out the exact text, without spacing. I had to use a helper to add spacing (but it was based on each word being capitalized, so "ThisIsSomeText" would show up as "This Is Some Text".
I am trying to write an MVC webpage that has two drop down lists. The content of the second list depends on what is selected in the first.
There does not seem to be a definitive way of doing this using built in MVC functions so I am going to have to roll my own. However I am not clear on the best way of getting all the functionality I require... which is "be the same as webforms" :)
I have created the dropdowns in a way similar to this
However I am not sure how to develop this so that if there is a 'selected' element in the first list when it is first bound this will flow through to automatically binding the second list on page load.
Edit:
Just to be clear I have the ability to bind the filtered list to the second dropdown. However if my Model contains a selection for the first dropdown the selection is set correctly but the second dropdown list does not fill.
(do I have to state I am newish to MVC and Javascript is like some alien language to me?)
Edit2:
I have thought about this a bit more.
Clearly I am strongly influenced by my time developing webforms and I don't quite 'get' MVC yet.
I think that really I have some things I should be catching in my model (ie if I already have the info to set the two dropdowns then I should in some way catch that in the controller and build the dropdowns pre set. Rather than trying to build an "ondatabound" type method and have the view call that (which was my initial intent)... Now I need to go and work out how to do that :)
This is one of the better implementations that I found. The question has also been discussed here.
You task contains 3 subtasks:
You should ajax get list of items for second ddl on changing selection of first ddl by using selected value
You should process action of getting list of items for 2-nd ddl by your Controller and return View with defined content of second ddl
You should update content of second ddl by getting result of processed action
<script type="text/javascript">
$(function(){
$("form #ddl_1").change(function(){
$.get({ // get request
url: "#Url.Action("MyController", "GetList"})" + "/" + $(this).val,
success: function(data){ // updating
$("form #ddl_2").html(data);
}
})
});
</script>
"GetList" action should take parameter "id" if you use default routes table (or you need to create special record at routes table with custom) and return partial view (without master page) with list of options for your ddl2, like this:
<option value="1">First</option>
<option selected value="2">Second</option>
<option value="3">Third</option>
See this blog post for creating cascading dropdown lists in asp.net mvc with downloadable source code.
For some reason I'm stuck on this. I need to filter results from a View based on a DropDownList in the same view. The basic idea is this: I have a list of providers that belong to various partners, but the provider list contains ALL the providers together (for all partners). I need to be able to display the providers by partner when someone wants to see just that partner (otherwise, the default listing will be ALL providers). My view currently is the "default" (showing all), but for some reason Im sitting here staring at the monitor (for the last 2 hours!) trying to figure out how to filter these results.
Any suggestions where to start/how to do it?!
EDIT: If you want to do this with jQuery and AJAX (which will provide a better user experience because only the subdivisions list will refresh), see this tutorial.
If I understand correctly, you basically want to do a WebForms-style postback.
Let's say you have a control with countries and country subdivisions (e.g. states, provinces, etc). When the country changes, you want the appropriate subdivisions to display.
So this would be view:
<% using (Html.BeginForm()) { %>
<%=Html.DropDownList("Address.CountryId", new SelectList(Country.GetAll(), "Id", "Name"), new { onchange = "this.form.submit();" })%>
<%=Html.DropDownList("Address.CountrySubdivisionId", new SelectList(CountrySubDivision.GetByCountryId(Model.CountryId), "Id", "Name"))%>
<input type="submit" name="btnSubmit" value="Submit"/>
<%} %>
This is the key to getting the dependent list to filter:
new { onchange = "this.form.submit();" }
And in the controller, you'd have something like this:
[AcceptVerbs(HttpVerbs.Post)]
public ViewResult Index(string btnSubmit)
{
if (btnSubmit == null)
{
// return the view displayed upon GET
}
else
{
// process the submitted data
}
}
In the above code, if the form submission was triggered by changing the value in a dropdown, btnSubmit will be null. Thus, the action you are POSTing to can tell whether or not the user meant to finalize her changes.
To add upon the earlier answers.
To create a drop down (in ASP .NET MVC 3) I did the following:
Add code to Index.cshtml
#using (Html.BeginForm())
{
#Html.DropDownList("EmployeeId", (SelectList)ViewData["EmployeeId"])
<input type="submit" name="btnSubmit" value="Submit"/>
}
Add code to YourModelNameController.cs in the default ActionResult for Index()
public ActionResult Index()
{
//create a selectlist
var employeeList = from el in db.Employee select el;
ViewData["EmployeeId"] = new SelectList(employeeList, "EmployeeId", "TmName");
return View(modelName);
}
There are many ways to skin this cat. Here's one.
Enclose your DropDownList in a form with METHOD=GET.
<form action="" method="get">
<select name="provider">
<option>1</option>
<!-- etc -->
</select>
</form>
Then, in you controller, filter based on the value of provider that was passed in. Remember to treat it as a Nullable parameter so that you can have some kind of behavior when it's empty.
Without posting some of your current code, it's tough to get much more specific than that.
Let's assume that you're probably passing a model to the view and that model is a list or IEnummerable of partners. What you want to do is restrict the list. In order to do that add a drop down list in the view and fill it with some possible partners. This can be done either by putting a list in ViewData or expanding the model passed back to the view. Both have advantages. Now when you change the drop down reload the page but append a parameter which is the filter. In the controller check for that parameter in the action, if it isn't present then return an unfiltered list, if it is then apply a filter and return the list. The view will just dumbly display whatever you give it.
As for the filtering you might want to try using LINQ.
You probably want a parameter to your controller action, maybe a (nullable?) id of the provider, to filter the results already when you get them from DB. Then just use the same view to list them, and request a new list if the dropdownlist changes.
Best solution I know is that one.
http://gridmvc.codeplex.com/SourceControl/latest
I am new to ASP.NET MVC, particularly ajax operations. I have a form with a jquery dialog for adding items to a drop-down list. This posts to the controller action.
If nothing (ie void method) is returned from the Controller Action the page returns having updated the database, but obviously there no chnage to the form. What would be the best practice in updating the drop down list with the added id/value and selecting the item.
I think my options are:
1) Construct and return the html manually that makes up the new <select> tag
[this would be easy enough and work, but seems like I am missing something]
2) Use some kind of "helper" to construct the new html
[This seems to make sense]
3) Only return the id/value and add this to the list and select the item
[This seems like an overkill considering the item needs to be placed in the correct order etc]
4) Use some kind of Partial View
[Does this mean creating additional forms within ascx controls? not sure how this would effect submitting the main form its on? Also unless this is reusable by passing in parameters(not sure how thats done) maybe 2 is the option?]
UPDATE:
Having looked around a bit, it seems that generating html withing the controller is not a good idea. I have seen other posts that render partialviews to strings which I guess is what I need and separates concerns (since the html bits are in the ascx). Any comments on whether that is good practice.
look at the ContentResult you can specify the mime type of what you return (text/html)
You could alternatively make a control that take a IEnumerable of whatever you put in the selectlist, and build it using the view engine. That way you keep the formatting of the html (in this case a list of options) into a view, and not in your code.
<%# Control Language="C#"Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Article>>"%>
<%foreach (var article in Model){%>
<option><%:article.Title %></option>
<%} %>
I think I would go for that second one
From what I understood, the jQuery dialog contains a form that, when submitted, will post to an action which updates the database with some information. You want to get the newly added database information and update the same form that was used to trigger the database update.
If that is the case, then I think the best clean and logical option is to return JSON serialization of the items to be put in the drop down right after you update the database. Then, using jQuery, you would clear the drop down and append option tags into it.
You can also write a new, seperate action that returns the JSON serialization of the database objects you need. You would have jQuery call another post to this action as a callback to your first ajax post (the one used to update the database).
Here is a quick snippet
public ActionResult UpdateDatabase(string something)
{
/// update the database
IEnumerable<Items> items = getItemsFromDatabase(); // or w/e
var vals = items.Select(x=> new { value = x.ID, text = x.Name }); // something similar
return Json(vals);
}
Personally, I would write a separate function that returns JSON. This ensure separation of concerns, and gives me a function I can use in many different places.
Returning a JsonResult with all the items is the most versatile and least-bandwidth intensive solution as long as you are happy to iterate through the list in jQuery and update your drop-down list.
Using a partial view is nice for HTML that you can .load(...) directly into your select, but less versatile.
I would go with the JsonResult.
In your Controller:
public JsonResult UpdateItem(string sItem)
{
// 1. Insert new item into database if not exist...
// {update code here}
// 2. retrieve items from database:
IEnumerable<Item> Items = GetItems();
// 3. return enumerable list in JSON format:
return new JsonResult{ Data = new {Items = Items, Result = "OK" }};
}
On client-side:
Iterate through Items array and add the items to your list.
I've got a View where I use a naming-convention on my text-fields, to indicate what should be done with the content once it is posted back to my controller.
The format is similar to:
<input type="text" name="RegistrationLine#ID" />
for updates
<input type="text" name="CreateRegistrationLine#LineNumber" /> for create
Now since I'm using this Naming-convention, regular model-binding isn't possible. But I've been reading up a bit on the subject and did find a bit of an indication that it would be possible to write a custom model binder, that should be able to help parse and bind these form elements and instantiate the objects correctly.
Please read: Bind formValue to property of different name, ASP.NET MVC
This is a bit similar to what I am doing except, I have the additional complexity of having appended information in the formelement-name that I am trying to bind to.
Am I way off base here? and if not, can any of you drop a few lines of code to show how you would start this model-binder off..
If this is a very bad approach to what I am really trying to achieve, I would love to hear suggestions for better approaches. Just note that what I want to be able to do is post back both updates and creates in one go.
I kinda have to agree with #jfar and #omar. I don't think a custom model binder is where you want to be in this instance.
You can pass a complex type to your view and simply use the full stop like #jfar mentioned.
id="Model.Person.Name.FirstName" will happily bind to an object named Person that has a class in it called Name that has a property called FirstName.
Now if you want to do some special checks on the data you could implement a partial class which would do the validations etc and populate the ModelState errors.
public partial class Name
{
public void Validate(){ }
public int CreateRegistrationLine(){ }
public bool DoSpecialActions(){ }
}
It's a little unclear what your special actions are doing so my example above may not be what you want.