I have the following question regarding the MVC and Jquery. I would like to be able to call with JQuery an action serverside and then returned result bind to a drop down list.
At this moment i do have something like that but instead of SelectList i just get back an anonymous type collection.
I have following JQuery:
<script type="text/javascript">
(function ($) {
$.fn.cascade = function (options) {
var defaults = {};
var opts = $.extend(defaults, options);
return this.each(function () {
$(this).change(function () {
var selectedValue = $(this).val();
var params = {};
params[opts.paramName] = selectedValue;
$.getJSON(opts.url, params, function (items) {
opts.childSelect.empty();
$.each(items, function (index, item) {
opts.childSelect.append(
$('<option/>')
.attr('value', item.Id)
.text(item.Name)
);
});
});
});
});
};
})(jQuery);
$(function () {
$('#Location_CountryId').cascade({
url: '#Url.Action("Regions")',
paramName: 'countryId',
childSelect: $('#Location_RegionId')
});
$('#Location_RegionId').cascade({
url: '#Url.Action("Cities")',
paramName: 'regionId',
childSelect: $('#Location_CityId')
});
});
</script>
Which calls this action in mvc 3:
public ActionResult Cities(int regionId)
{
IList cities;
using (DatingEntities context = new DatingEntities())
{
cities = (from c in context.cities
where c.RegionID == regionId
select new
{
Id = c.CityId,
Name = c.Name
}).ToList();
};
return Json(cities, JsonRequestBehavior.AllowGet);
}
My question, can i then return SelectList instead of IList and bind it properly?
Could you provide an example with my code please? I have more complex behavriou just for simpleness i posted only part of.
Thanks
What about creating a partial that renders the html for the selectlist options and returing that?
_SelectList.cshtml:
#model IList<SelectListItem>
#{
foreach (var item in Model)
{
<option value=#item.Value>#item.Text</option>
}
}
And from your controller:
public ActionResult Cities(int regionId)
{
IList<SelectListItem> cities;
using (DatingEntities context = new DatingEntities())
{
cities = (from c in context.cities
where c.RegionID == regionId
select new SelectListItem()
{
Value = c.CityId,
Text = c.Name
}).ToList();
};
return PartialView("_SelectList", cities);
}
Your js can then look like this:
<script type="text/javascript">
(function ($) {
$.fn.cascade = function (options) {
var defaults = {};
var opts = $.extend(defaults, options);
return this.each(function () {
$(this).change(function () {
var selectedValue = $(this).val();
var params = {};
params[opts.paramName] = selectedValue;
$.get(opts.url, params, function (items) {
opts.childSelect.empty();
opts.childSelect.html(items);
}
});
});
};
})(jQuery);
$(function () {
$('#Location_CountryId').cascade({
url: '#Url.Action("Regions")',
paramName: 'countryId',
childSelect: $('#Location_RegionId')
});
$('#Location_RegionId').cascade({
url: '#Url.Action("Cities")',
paramName: 'regionId',
childSelect: $('#Location_CityId')
});
});
</script>
Although - I normally do something similar to your JSON code above :-)
HTH
How about just using some simple jQuery to iterate through the JSON object your Cities method returns. eg
<script>
$('#Location_RegionId').change(function () {
$.get('#Url.Action("Cities", "[ControllerName]")/' + $('#Location_RegionId').val(), function (data) {
$('#Location_CityId').empty();
$.each(data, function() {
$('#Location_CityId').append($('<option />').val(this.CityId).text(this.Name));
});
});
});
$('#Location_RegionId').change();
<script/>
Assuming that your select with the regions in is called Location_RegionId and your select with cities has an id of Location_CityId.
For this to work as above it will need to be at the bottom of your view file, so the #Url.Action is rendered into the appropriate URL. Otherwise you can hard code it into a .js file and surround it with document.ready.
in the controller after getting list of cities convert it to a select list item as below
var list=new List<SelectListItem>();
list.AddRange(cities.Select(o => new SelectListItem
{
Text = o.Name,
Value = o.CityId.ToString()
}));
}
return Json(list);
Related
I have a view with a script (included below) that fires on a dropdownlist change, and the event handler should fill values for two text inputs. Values are received from controller.
The problem I'm having is, as soon as itemstatus list is populated, the controller returns back to view, and no values are passed back to AJAX function.
If I remove itemstatus list code and manually assign values as follows, it works:
var result = new { Quantity = "123", Price = "555"};
then it works.
I've also tried other ways to get data within controller but results were the same. Do you have any ideas what am I doing wrong and why controller returns back to view before "return Json"
<script type="text/javascript">
$(document).ready(function() {
//Dropdownlist Selectedchange event
$("#dropdown1").change(function ()
{
$("#txtQuantity").empty();
$("#txtPrice").empty();
$.ajax(
{
type: 'POST',
url: '#Url.Action("GetValues")',
dataType: 'json',
data: { id: $("#dropdown1").val() },
success: function(data)
{
$("#txtQuantity").val(data.Quantity);
$("#txtPrice").val(data.Price);
}
})
})
});
Controller:
public JsonResult GetValues(int id)
{
List<Item> itemstatus =
(from pd in db.Item
where (pd.itemID == id)
select new Item()
{
itemPrice = pd.itemPrice,
itemQuantity = pd.itemQuantity
}).ToList();
...
more code where i select what i need as a result i have two strings named itemquantity and itemprice
...
var result = new { Quantity= itemquantity, Price = itemprice };
return Json(result, JsonRequestBehavior.AllowGet);
}
because you are sending a list, whose data values can be accessed using
success: function(data)
{
$("#txtQuantity").val(data[0].Quantity);
$("#txtPrice").val(data[0].Price);
}
I'm trying to code a simple autocomplete using LINQ to entities and Razor (new to c# sharp as well) and i'm having trouble displaying json data in my view.
My controller is as follows:
public ActionResult AutoCompleteCity(string guess)
{
List<City> listData = null;
if (!string.IsNullOrEmpty(guess))
{
listData = db.AutoCompleteCity(guess);
}
return Json(new { Data = listData });
}
AJAX call:
function getCities(input) {
var serviceURL = $("#autocompleteURL").val();
var url =
$.ajax({
type: "POST",
url: serviceURL,
data: {
'guess': input
},
dataType: 'json',
success: function (response) {
if (response.Data != null) {
if ($("#targetUL") != undefined) {
$("#targetUL").remove();
}
Data = response.Data;
$.each(Data, function (i, value) {
$("#targetUL").append($("<li class='targetLI' onclick='javascript:agregarTexto(this)'>" + JSON.stringify(value) + "</li>"));
});
});
}
I might be missing a bracket or two :D
Any way when i retrieve records from the database and try to pass JSON values to the view the output is:
{"Data":[{"Selected":false,"Text":null,"Value":null}]}
I assume I'm not passing the JSON listData correctly. Any input will be greatly appreciated, thanks!
EDIT: here is a screencap of the values returned by listData in my controller
This is my LINQ query
public List<City> AutoCompleteCity(string guess)
{
using (var context = new Sports.SportsEntities())
{
var query = (from loc in context.city
join prov in context.state on loc.STATE_ID equals prov.STATE_ID
where loc.CITY_DESC.Contains(guess.ToUpper())
select new
{
city = loc.CITY_DESC,
state = prov.STATE_DESC,
});
IEnumerable<City> cityList= from ba in query.AsEnumerable()
select new City(ba.city, ba.state);
return cityList.ToList();
}
}
This error:
{"Data":[{"Selected":false,"Text":null,"Value":null}]}
was caused by having declared private attributes in the City Class, or by failing to declare getter/setter methods if said attributes are meant to be private.
I figured that out by looking at the screen capture posted on my question, only displaying the "selected", "text" and "value" properties and not the city and state description in the query results, which was what I needed to display below the textbox input.
This controller method will do the trick:
public JsonResult AutoCompleteCity(string term)
{
List<City> listData = new List<City>();
if (!string.IsNullOrEmpty(term))
{
listData = db.AutoCompleteCity(term);
}
return Json(listData, JsonRequestBehavior.AllowGet);
}
The problem is probably this piece of code in the AJAX call:
if ($("#targetUL") != undefined) {
$("#targetUL").remove();
}
By doing this you are removing the ul tag from the DOM and therefore cannot add the li elements you are constructing in this piece of code:
$.each(Data, function (i, value) {
$("#targetUL").append($("<li class='targetLI' onclick='javascript:agregarTexto(this)'>" + JSON.stringify(value) + "</li>"));
});
If you want to clear the list use .empty():
if ($("#targetUL") != undefined) {
$("#targetUL").empty();
}
if you want to return a JSON, change that:
public ActionResult AutoCompleteCity(string guess)
by
public JsonResult AutoCompleteCity(string guess)
and also try that:
Data = JSON.parse(response.Data);
It looks like your method returns a list of City objects, so maybe you need to use the property of that objects to get to the city name, something like this:
$.each(Data, function (i, city) {
$("#targetUL").append($("<li class='targetLI' onclick='javascript:agregarTexto(this)'>" + city.Name + "</li>"));
});
I have dropdown list which was created dynamically like:
#for(int i=0;i<=count;i++)
{
#Html.DropDownListFor(m => m.GetTimeSheetDetails[i].PROJ_ID, (SelectList)ViewBag.ProjectList, "-- Choose a Project --", new { #class = "ddlProjectvalue" })
}
<input type="submit" value="Add Record" name="btn"/>
in Contoller I am loading data to dropdownlist:
[HttpPost]
Public ActionResult Timesheet()
{
TimsheetModel model=new TimesheetModel();
if(btn=="Add Record")
{
var data= Session["ddlData"] as IEnumerable<SelectListItem>;
SelectList list1=new SelectList(data,"Value","Text",model.ProjID);
ViewBag.ProjectList=list1;
count++; // ADDS NEW RECORD
return View();
}
else
{
var result = (from proj in db.PROJECTs where proj.IS_DELETED == "N" select new { Value = proj.ID, Text = proj.NAME })
SelectList list = new SelectList(result, "Value", "Text", tm.PROJ_ID);
ViewBag.ProjectList = list;//Data loaded here for Dropdown list
}
return View();
}
Now My Scenario is if count=5 which means if we have five dropdown lists, when I select item in first dropdown list should not show in second dropdown list and if we have select item in second dropownlist should not show items of first and second in third dropdown list. for that I have written script like:
<script>
$(document).ready(function () {
$('.ddlProjectvalue').change(function () {
var id = $('.ddlProjectvalue').attr('id');
var selector = "#" + id;
var selectedValue = $(this).val();
$.ajax({
url: "#Url.Action("GetDDLData","Employer")",
data: { selectedValue: selectedValue, id: id },
dataType: "json",
type: "GET",
error: function () {
alert(" An error occurred.");
},
success: function (data) {
debugger;
$("" + selector + "").removeClass("ddlProjectvalue");
$('.ddlProjectvalue').empty();
var optionhtml1 = '<option value="' +
0 + '">' + "--Choose a Project--" + '</option>';
$(".ddlProjectvalue").append(optionhtml1);
$.each(data, function (i) {
var optionhtml = '<option value="' +
data[i].Value + '">' + data[i].Text + '</option>';
$(".ddlProjectvalue").append(optionhtml);
});
}
});
});
});
</script>
and when i pass selected value to controller like:
public ActionResult GetDDLData(string selectedValue, string id, string addrecord)
{
int projectid = Convert.ToInt32(selectedValue);
if (id == "GetTimeSheetDetails_0__PROJ_ID")
{
IEnumerable<SelectListItem> projectslist = (from proj in db.PROJECTs where proj.IS_DELETED == "N" && proj.ID != projectid select proj).AsEnumerable().Select(projt => new SelectListItem() { Text = projt.NAME, Value = projt.ID.ToString() });
var result = new SelectList(projectslist, "Value", "Text", tm.PROJ_ID).ToList();
Session["ddlData"] = result;
ViewBag.ProjectList = result;
return Json(result, JsonRequestBehavior.AllowGet);
}
else
{
var result = Session["ddlData"] as IEnumerable<SelectListItem>;
var query = (from data in result where data.Value != selectedValue select data) as IEnumerable<SelectListItem>;
Session["ddlData"] = query;
return Json(result, JsonRequestBehavior.AllowGet);
}
}
Now my problem is when I add new record by clciking on Add button, loading Session["ddldata"] data to total dropdown list instead it should remain selectlist item in first dropdownlist for first time, I need like when i first select a dropdownlist item in first dropdown list it should remain same when add record also. it means i should prevent server side load on first select list item and vice versa.
Note: Due to some issues i should add record on server side only
How I can prevent it, I tried like preventDefault or return false using jquery, but not working, Any Ideas? how can I fix it.
I think you are overcomplicating things here. You don't really need to request new options from server. Why not just filter the option out on the javascript side?
$(document).ready(function() {
$('.ddlProjectvalue').change(function() {
updateDDLValues();
});
updateDDLValues();
});
function updateDDLValues() {
// Display all
$('.ddlProjectvalue option').show();
// Hide all selected options from other selectlists
$('.ddlProjectvalue').each(function(i,element) {
var selectedvalue = $(element).find('option:selected').val();
$('.ddlProjectvalue').not(element).find('option[value="'+selectedvalue+'"]').hide();
});
}
Fiddle:
http://jsfiddle.net/Pt7qV/2/
Update:
As for the serverside part of your question, there are some serious flaws in your code. You increase the count property in your controller and use the variable clientside. First you'd think that's how it's done but nope it doesn't work that way.
You are returning View when Add Record is submitted but you aren't returning any model with it.
Your TimsheetModel would look something like this:
public class TimsheetModel
{
public int Count {get; set;}
}
In your controller you pass this to the view:
TimsheetModel model=new TimesheetModel();
if(btn=="Add Record")
{
var data= Session["ddlData"] as IEnumerable<SelectListItem>;
SelectList list1=new SelectList(data,"Value","Text",model.ProjID);
ViewBag.ProjectList=list1;
model.Count++; // ADDS NEW RECORD
return View(model);
}
And in your view:
#model TimsheetModel
#for(int i=0;i<=Model.Count;i++)
{
#Html.DropDownListFor(m => m.GetTimeSheetDetails[i].PROJ_ID, (SelectList)ViewBag.ProjectList, "-- Choose a Project --", new { #class = "ddlProjectvalue" })
}
<input type="submit" value="Add Record" name="btn"/>
I'd suggest you to go back to tutorials or books a bit, this is quite basic stuff after all. I won't go into how you are going to handle database side etc. since I think this answer would just escalate into explaining basic stuff.
I am attempting to create a cascading dropdown with MVC3. The parent dropdown is called "Category", when the user selects a Category, a child dropdown is then populated with a list of pictures that belong to that Category. I've got some code in place right now, and I am able to call the controller from the View when the user selects a category. Here is my code:
Controller:
public ActionResult Pictures(int catId)
{
var k = ((List<Picture>) ViewBag.AllPictures)
.FindAll(x => x.CategoryId == catId)
.Select(x => new
{
Value = x.PictureId,
Text = x.Title
});
return Json(k, JsonRequestBehavior.AllowGet);
}
View:
<div class="editor-field">
#Html.DropDownListFor(model => model.Picture.PictureId, Enumerable.Empty<SelectListItem>(), new { #id = "pictureFilter" })
#Html.ValidationMessageFor(model => model.Picture.PictureId)
</div>
Javascript:
<script type="text/javascript">
$('#ddlFilter').on("change", function() {
var selectedCat = $(this).val();
$.getJSON("/StoreManager/Pictures", { catId: selectedCat }, function(pictures) {
var picturesSelect = $('#pictureFilter');
picturesSelect.empty();
$.each(pictures, function(index, picture) {
picturesSelect.append($('<option/>', {
value: picture.val,
text: picture.text
}));
});
});
});
</script>
When I take a look at variable 'k', that my controller is returning. It does contain all the correct collection items for the pictures, with their respective 'value' and 'text' fields assigned. When it returns the JSON back to the View, it creates a dropdown menu with the exact number of fields that should be there, but they all contain empty data. When I inspect the element in Chrome, here is the HTML afterwards:
<option><option/>
<option><option/>
<option><option/>
<option><option/>
All help is appreciated. Any further code requested will be linked to in pastebin posts.
You have return JSON then you need to used same variables as you send from Pictures controller.
try this:
<script type="text/javascript">
$('#ddlFilter').on("change", function() {
var selectedCat = $(this).val();
$.getJSON("/StoreManager/Pictures", { catId: selectedCat }, function(pictures) {
var picturesSelect = $('#pictureFilter');
picturesSelect.empty();
$.each(pictures, function(index, picture) {
picturesSelect.append($('<option/>', {
value: picture.Value,
text: picture.Text
}));
});
});
});
</script>
or you can also check the response variable get from your Action method by using firebug console tab.
I am having some difficulty figuring out how to return the selected item in my HTML.DropDownList so that upon hitting a submit button, the selected item text will be looked up in my database. Here is what I have:
#{
var selectStaff = "Select LastName + ', ' + FirstName AS Name, StaffID From StaffList ORDER BY LastName";
var data = db.Query(selectStaff);
var items = data.Select(i => new SelectListItem {
Text = i.Name
});
}
And then in the html..
#Html.DropDownList("Select1", items)
This works fine, as my dropdownlist is appearing and is populated, but now upon hitting a submit button, I want to be able to search that text of the selected item in my database. How would I go about doing this?
If you don't bind the dropdown to a property on your view model (which would be preferable), you can still get it simply using Request.Form["Select1"] in your controller action.
If you mean that you want to be able to get the value while still on the razor page, you need to use jQuery (or other javascript) to get the value.
To get the value with jQuery:
$(document).ready(function () {
$("#YourSubmitButtonID").click(function () {
// Get the value from 'Select1'
var value = $("#Select1").val();
});
});
To do something with the value, you would have to use an ajax function, something like this:
$.ajax({
url: '#Url.Action("ActionName", "ControllerName")',
data: { valueToQuery: $("#Select1").val() },
success: function (data) {
// The data is the result
}
});
On the controller named ControllerName in this example, you'd have the code that queries the database and returns your result.
public ActionResult ActionName(string valueToQuery)
{
// Do your stuff here
return Json("your result", , JsonRequestBehavior.AllowGet);
{
I have also found THIS very interesting that May help you out!
You may also try the following Steps if you don't want to use Ajax or Json tactics:
var sql = "SELECT ProductId, ProductName FROM Products";
var data = Database.Open("Northwind").Query(sql);
var items = data.Select(i => new SelectListItem {
Value = i.ProductId.ToString(),
Text = i.ProductName
});
#Html.DropDownList("productid", items)
And Also:
var sql = "SELECT ProductId, ProductName FROM Products";
var data = Database.Open("Northwind").Query(sql);
<select name="productid">
#foreach(var row in data){
<option value="#row.ProductId">#row.ProductName</option>
}
</select>