Cascading Dropdown in Mvc3 - asp.net-mvc-3

I am using Mvc3 I have 2 dropdown,BankBranch and city.
On first time load of view i am binding both the dropdon without cascading. then if user select city i want to change bankbranch according to that.
I am confused how i can achieve both the things together.
Thanks in advance.

This blog post should get you on your way. It provides examples for normal form posts, microsoft ajax form post, jquery ajax and others.
http://weblogs.asp.net/raduenuca/archive/2011/03/06/asp-net-mvc-cascading-dropdown-lists-tutorial-part-1-defining-the-problem-and-the-context.aspx
EDIT:
Generalized Code Explanation
Model
public class CascadeModel {
public SelectList<City> Cities { get; set; }
public SelectList<BankBranch> BankBranches { get; set;}
public int CityId { get; set; }
public int BranchId { get; set; }
}
public class Branch {
public int Id { get; set;}
public string Name { get; set; }
}
Controller:
public ActionResult BranchSelector() {
var viewData = new CascadeModel();
viewData.Cities = new SelectList(Repository.GetAllCities(), "Id", "Name", selectedCity);
viewData.BankBranches = new SelectList(Repository.GetBranchesByCity(selectedCity), "Id", "Name", "");
return View(viewData);
}
public JsonResult GetBranches(int id) {
return Json(Repository.GetBranchesByCity(id), JsonRequestBehavior.AllowGet);
}
View:
#model CascadeModel
#Html.DropDownListFor(m => m.CityId, Model.Cities, new { style = "width:250px" })
<br />
#Html.DropDownListFor(m => m.BranchId, Model.BankBranches, new { style = "width:250px" })
<script type="text/javascript">
$(document).ready(function() {
$("#CityId").bind('change', function() {
$.ajax({
url: '/Controller/GetBranches/' + $(this).val(),
success: function(data) {
//Clear the current branch ddl
//Load the new Branch data returned from the jquery call in the branches ddl
}
});
};
});
</script>

Related

Ajax POST insert half data(some data is missed) Asp.Net MVC Ajax

I am inserting data via Ajax Post method. Data is inserted in one table but the data for secod table is not inserting. I have checked the code but I am not sure that what is mising in my code.
When I use the direct controller method then the data is inserted in both table but when I use the Ajax then data is inserted in only one table.
My Old working Controller code:
[HttpPost]
public ActionResult Create(StudentModel model)
{
if(ModelState.IsValid)
{
int id = stude.AddStudent(model);
if(id>0)
{
ModelState.Clear();
ViewBag.Success = "Data added Successfully";
}
}
return View();
}
My Ajax Controller Code:
[HttpPost]
public JsonResult Creates(StudentModel model)
{
if (ModelState.IsValid)
{
int id = stude.AddStudent(model);
if (id > 0)
{
ModelState.Clear();
ViewBag.Success = "Data added Successfully";
return Json("success", JsonRequestBehavior.AllowGet);
}
}
return Json("issue", JsonRequestBehavior.AllowGet);
}
My Model Code:
public int AddStudent(StudentModel stu)
{
student stud = new student()
{
FName = stu.FName,
LName = stu.LName,
Email = stu.Email
};
if (stu.address != null) {
stud.address= new address()
{
Details = stu.address.Details,
Country = stu.address.Country,
State = stu.address.State
};
}
using (var context = new StudentEntities())
{
context.students.Add(stud);
context.SaveChanges();
}
return stud.Id;
}
My Js/Ajax Code:
$(document).ready(function () {
//Add record
$("#add").click(function (e) {
e.preventDefault();
// var id = $();
var fname = $("#FName").val();
var lname = $("#LName").val();
var email = $("#Email").val();
var details = $("#Details").val();
var country = $("#Country").val();
var state = $("#State").val();
$.ajax({
async: true,
method: "POST",
url: '#Url.Action("Creates")',
data: JSON.stringify({
FName: fname, LName: lname, Email: email, Details: details,County: country, State: state
}),
dataType: 'JSON',
contentType: "application/json; charset=utf-8",
success: function (data) {
//window.location = data.newurl;
console.log(data);
},
error: function (err) {
alert('Failed to get data' + err);
}
});
return false;
});
});
Data is inserted in only student table and for the address table it returns null/empty and the data is skipped, although the same code will work if I remove the Ajax. But I want to use the Ajax so things will work smoothly.
Any help will be appreciated.
Update: Student Model class:
I am using N-Tire/3-Tire Architecture
My Student class Properties
public class StudentModel
{
public int Id { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public string Email { get; set; }
public Nullable<int> AddressId { get; set; }
public AddressModel address { get; set; }
}
My Address Class Properties
public class AddressModel
{
public int Id { get; set; }
public string Details { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
}
There were a lot of issues in my code. I am listing it below.
The main, which I think case the problem is the Id's of my textboxes, as I am using Razor Engine and it creates the id automatic, which cause the issue, So I fix it by adding the Id and Name manually, like
#Html.EditorFor(model => model.address.Details, new { htmlAttributes = new { #class = "form-control", Name="Details", Id="Details"} })
I have changed my ajax data code to:
FName: fname, LName: lname, Email: email, address: { Details: details, Country: country, State: state }
For success message I have change Return message in my controller like:
var scess = "Data added Successfully";
return Json(new { success = true, scess }, JsonRequestBehavior.AllowGet);
and in my view I have add this line in my ajax success call:
success: function (data) {
$("#msg").text(data.scess);
console.log(data);
},
Hope this will also help other users in future.

How do I populate a drop-down list with List<string> using knockout.JS

I'm playing around with knockoutJS and am struggling to get a drop-down populated with data from my model.
I'm guessing I need to convert the model data to a JSON first but for the life of me can't figure it out.
I have a basic class:
public class QuoteViewModel
{
public QuoteViewModel()
{
QuoteLines = new List<QuoteLine>();
}
public int QuoteHeaderId { get; set; }
public string QuoteNumber { get; set; }
public string Status { get; set; }
public DateTime DateCreated { get; set; }
[DisplayName("Customer")]
public SalesCustomer SelectedCustomer { get; set; }
public List<string> Customers { get; set; }
public List<QuoteLine> QuoteLines { get; set; }
}
I have an ActionMethod in a controller:
[HttpGet]
public ActionResult CreateQuote()
{
QuoteViewModel quote = new QuoteViewModel();
quote.QuoteNumber = "";
quote.Status = "P";
quote.Customers = _dbContext.SalesCustomers.Select(x => x.CustomerName).ToList();
quote.QuoteLines = new List<QuoteLine>();
return View(quote);
}
And the View():
Razor:
<select class="form-control" id="SelectedCustomer" data-bind="options: availableCustomers, optionsText: 'CustomerName', value: SelectedCustomer, optionsCaption: 'Choose...'"></select>
ViewModel:
function QuoteViewModel() {
var self = this;
self.Id = ko.observable('#Model.QuoteHeaderId');
self.QuoteNumber = ko.observable();
self.Status = ko.observable('#Model.Status');
self.DateCreated = ko.observable();
self.availableCustomers = JSON.parse('#Html.Raw(Model.Customers)');
#*$.ajax({
type: "GET",
url: '#Url.Action("GetCustomers", "Test")',
success: function (data) {
$.each(data, function (index, value) {
self.availableCustomers.push(new Customer(value));
});
},
error: function (err) {
console.log(err.responseText);
}
});*#
self.SelectedCustomer = ko.observable();
self.QuoteLines = ko.observableArray([]);
self.AddQuoteLine = function (sku, description, bomDetails) {
self.QuoteLines.push(new QuoteLineViewModel(sku, description, bomDetails));
}
self.SaveToDatabase = function () {
var dataToSend = ko.mapping.toJSON(self);
$.ajax({
type: "POST",
url: '#Url.Action("CreateQuote", "Test")',
contentType: 'application/json',
data: dataToSend,
success: function (data) {
},
error: function (err) {
console.log(err.responseText);
}
});
}
The commented out code uses ajax to get the customers and push it onto the array and that works, but is there not a way to do it directly from the model data?
Edit 1:
I don't need access to the whole SalesCustomer object, just the string name:
If I change my code as such:
Controller:
quote.Customers = _dbContext.SalesCustomers.Select(x => x.CustomerName.Trim()).ToList();
Model class property:
public List<string> Customers { get; set; }
Razor:
<select class="form-control" id="SelectedCustomer" data-bind="options: availableCustomers, value: SelectedCustomer, optionsCaption: 'Choose...'"></select>
Javascript:
self.availableCustomers = ko.observableArray([]);
var customers = '#Html.Raw(JsonConvert.SerializeObject(Model.Customers))';
self.availableCustomers = JSON.parse(customers);
self.SelectedCustomer = ko.observable();
Now the drop-down is populated with the string values of customer names. However the selected customer is not passed back to controller on POST?
Edit 2:
Well I'm not sure why its working now, but it is.
The code is the same as in Edit 1.
The only thing I can think of is I was that I erroneously had the SelectedCustomer property type still set to SalesCustomer which will obviously not work:
public SalesCustomer SelectedCustomer { get; set; }
when it should be:
public string SelectedCustomer { get; set; }
Thank you user3297291 for the assistance in pointing me in right direction.

How to send Model value as parameter while submitting #Ajax.Beginform()

I am using #Ajax.Beginform in my View which is tightly bound to the ViewModel.
I've #Html.ListBoxFor inside my form. I add and delete items from the listbox using jQuery. Now what I am want to achieve is that onpress of the submit button, it should send full data present in the listbox regardless of which are selected. Currently it sends the list to controller if I select all the item in the listbox and press submit button. But I don't want to do that. Any idea as to how to achieve this?
Can it be sent as a form parameter.
#using (Ajax.BeginForm("SaveTextComponent", "LoanFilterEditor", new{ param1 = Model.listBoxItem}, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SUCCESS" }))
I try to accept the parameter in the controller like this
public ActionResult SaveTextComponent(TextComponentViewModel model, List<SelectListItem> list)
{
}
But list is null.. Please help.
Maybe you can use this javascript to select all items at your listbox and then, send it to controller:
function listbox_selectall(listID, isSelect) {
var listbox = document.getElementById(listID);
for(var count=0; count < listbox.options.length; count++) {
listbox.options[count].selected = isSelect;
}
}
And after that, you can call the function on your form in this way:
<script>
function submit() {
listbox_selectall('righthand_side_listbox_id', true);
return true;
}
</script>
<form onsubmit="return submit()">
...
</form>
Credits to Viral Patel blog
You can follow my example:
Model:
pulic class TextComponentViewModel {
public int[] SelectedListItem { get; set; }
public List<Item> ListItem { get; set; }
}
public class Item {
public int Id { get; set; }
public String Name { get; set; }
}
View:
#model TextComponentViewModel
#using (Ajax.BeginForm("SaveTextComponent", "LoanFilterEditor", null, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SUCCESS" }, new {name = "mainForm", id = "mainForm"}))
{
#Html.ListBoxFor(model => model.SelectedListItem , new MultiSelectList(Model.ListItem, "ID", "Name"))
for(var i = 0; i < Model.ListItem.Count();i++ )
{
#Html.HiddenFor(m => m.ListItem[i].Id)
#Html.HiddenFor(m => m.ListItem[i].Name)
}
<input type = "submit" id="submitButton" />
}
Controller:
public ActionResult SaveTextComponent(TextComponentViewModel model)
{
}
Script:
$("#submitButton").click(function(){
$("#mainForm").submit();
});

Ajax paged list pass object to controller

I am working on some advanced searching functionality and I have run into a roadblock. I would like to use AJAX for my search results and use the PagedList additons to handle paging. I have an AdvancedSearchResults action which takes a search filters class and the current page. The issue is how can I pass the search Filters class into this action correctly. I am sure something I am doing just isnt organized correctly as I would think this would be fairly common. I would really appreciate any help. Thanks in advance.
Controller Action:
public ActionResult AdvancedSearchResults(AdvancedSearchFilters searchFilters, int ? page)
{
//DO STUFF
return PartialView("_SearchResults", results);
}
AdvancedSearchResults Filters:
public class AdvancedSearchFilters
{
public string SearchText { get; set; }
public List<string> SelectedTableTypes { get; set; }
public List<Guid> SelectedGenreIds { get; set; }
public List<Guid> SelectedPlatformIds { get; set; }
public int YearMax { get; set; }
public int YearMin { get; set; }
public int RatingMin { get; set; }
public int RatingMax { get; set; }
}
Search Results Partial View:
#model List<SearchResultItem>
#using PagedList
#using PagedList.Mvc
<!-- 15 Per Page -->
<h2>Search Results</h2>
#if (ViewBag.OnePageOfSearchItems.Count > 0)
{
<div class="pagination">
#Html.PagedListPager((IPagedList)ViewBag.OnePageOfSearchItems, page => Url.Action("AdvancedSearchResults", "Search", new { searchFilters = ViewBag.AdvancedSearchFilters, page = page }),
PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(PagedListRenderOptions.OnlyShowFivePagesAtATime, "#main-results"))
</div>
foreach (var searchResultItem in Model)
{
<a href="#Url.Action(searchResultItem.ResultType, searchResultItem.ResultType, new { id = searchResultItem.ResultId })" class="result">
#if (searchResultItem.ProfileImageLocation != null)
{
<img src="#searchResultItem.ProfileImageLocation" alt="#searchResultItem.ResultName" />
}
<div class="result-info">
<h3>#searchResultItem.ResultName</h3>
<p>#searchResultItem.DisplayText</p>
</div>
</a>
}
<div class="pagination">
#Html.PagedListPager((IPagedList)ViewBag.OnePageOfSearchItems, page => Url.Action("AdvancedSearchResults", "Search", new { searchFilters = ViewBag.AdvancedSearchFilters , page = page }),
PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(PagedListRenderOptions.OnlyShowFivePagesAtATime, "#main-results"))
</div>
}
else
{
<span>No Matches.</span>
}
Try passing the data to action method in the form of json. Try the below code which pass the json object to action method.
//// construct your json object.
var jsonObj = '{"SelectedTableTypes" : [{"1","2"}]}';
var postData = $.parseJSON(jsonObj);
$.ajax(
{
url: // your URL with Action name AdvancedSearchResults,
data: postData,
cache: false,
dataType: "json",
success: function (result) {
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});

Master-Detail Sample Code for MVC 3 Razor (using Ajax for details)

I am looking for sample code to create a master/details with c# mvc 3.
Specifically, I am trying to figure out how to call via ajax the rendering of a partial view. I am able to put the partial view on the form but want to populate it after a user has selected an item from a select list via ajax.
thx
As always you start with the model:
public class MyViewModel
{
public int Id { get; set; }
public string Title { get; set; }
}
public class DetailsViewModel
{
public string Foo { get; set; }
public string Bar { get; set; }
}
then a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
// TODO: don't hardcode, fetch from repository
var model = Enumerable.Range(1, 10).Select(x => new MyViewModel
{
Id = x,
Title = "item " + x
});
return View(model);
}
public ActionResult Details(int id)
{
// TODO: don't hardcode, fetch from repository
var model = new DetailsViewModel
{
Foo = "foo detail " + id,
Bar = "bar detail " + id
};
return PartialView(model);
}
}
and corresponding views.
~/Views/Home/Index.cshtml:
#model IEnumerable<MyViewModel>
<ul>
#Html.DisplayForModel()
</ul>
<div id="details"></div>
<script type="text/javascript">
$(function () {
$('.detailsLink').click(function () {
$('#details').load(this.href);
return false;
});
});
</script>
~/Views/Home/Details.cshtml:
#model DetailsViewModel
#Model.Foo
#Model.Bar
~/Views/Home/DisplayTemplates/MyViewModel.cshtml:
#model MyViewModel
<li>
#Html.ActionLink(Model.Title, "details", new { id = Model.Id }, new { #class = "detailsLink" })
</li>
I have blogged about creating master detail form using asp.net mvc where you can add n child records on clietn side without the need of sending ajax request just to bring the editor fields for child records. it used jquery templates

Resources