I have two drop down lists which are District & School. I would like whenever I choose a district from the list, the values that are in the school list will change at the same time. I am using ajax to try and post the data to another controller but the school list does not change at all. It contains the names of all schools no matter which district I select. I am thinking it has something to do with the line Schools = new SelectList(db.Schools.ToList(), "schoolID", "name")in my SchoolDistrictInformation controller. Here is what I am working with so far:
The security code is a code that must be entered and corresponds with the selected district. It must match with the code in the database or the form will not be submitted.
View Model:
public class DistrictSchoolListViewModel
{
public SelectList Districts { get; set; }
public SelectList Schools { get; set; }
public string SelectedSchool { get; set; }
public string SelectedDistrict { get; set; }
[Required(ErrorMessage = "This code is required")]
public string DistrictCode { get; set; }
}
Controllers:
public ActionResult SchoolDistrictInformation()
{
var viewModel = new DistrictSchoolListViewModel()
{
Districts = new SelectList(db.Districts.ToList(), "leaID", "name"),
Schools = new SelectList(db.Schools.ToList(), "schoolID", "name")
};
return View(viewModel);
}
[HttpPost]
public ActionResult GetSchools(DistrictSchoolListViewModel model)
{
var selectedDistrict = model.SelectedDistrict;
var schools = findSchools(selectedDistrict);
IEnumerable<SelectListItem> filteredSchools =
schools.Select(m => new SelectListItem { Text = m.name, Value = m.schoolID.ToString() });
return PartialView("SchoolDistrictInformation", filteredSchools);
}
School Table Query:
internal IQueryable<School> findSchools(string district)
{
var query = from School in db.Schools
where School.leaID.Equals(district)
select School;
return query;
}
School District Information View:
#model Staff_Form.Models.DistrictSchoolListViewModel
<h2>Select District and School from list</h2>
<script type="text/javascript" src="/scripts/jquery-1.4.4.js"></script>
<script type="text/javascript">
$('#SelectedDistrict').on('change', function () {
$.ajax({
type: "POST",
url: 'Controller/GetSchools',
data: $(this).val(),
success: function (response) {
$('#SelectedSchool').html(response);
}
});
});
</script>
<div>
<form action="#Url.Action("StaffInformation", "Staff")" method="get">
District: #Html.DropDownListFor(m => m.SelectedDistrict, Model.Districts, "----Select----")
Security Code: #Html.TextBoxFor(m => m.DistrictCode) <br />
School: #Html.DropDownListFor(m => m.SelectedSchool, Model.Schools, "----Select----")
<input type="submit" value="Submit" />
</form>
</div>
Get Schools View:
#model System.Collections.Generic.IEnumerable<System.Web.Mvc.SelectListItem>
#{ Layout = null;}
#foreach (var school in Model)
{
<option value="#school.Value">#school.Text</option>
}
I appreciate any and all help given towards the solution of this question. Thank you!
Your script is before the the element with id="SelectedDistrict" and not wrapped in $(document).ready() so your attaching an event to an element which does not even exist at that point.
Move the script to the bottom of the page (immediately before the closing </body? tag and/or wrap it inside document.ready
$(document).ready(function() { // or $(function() {
$('#SelectedDistrict').on('change', function () {
....
});
});
Side note: Update your version of jquery to a recent version and consider returning json to populate your 2nd dropdown (refer this answer)
You should include the property name when you pass the district back to the GetSchools action
$('#SelectedDistrict').on('change', function () {
$.ajax({
type: "POST",
url: 'Controller/GetSchools',
data: { SelectedDistrict: $(this).val() },
success: function (response) {
$('#SelectedSchool').html(response);
}
});
});
Related
I am a newbie to spring boot and thymeleaf,
I have a list of books ina table with checkboxes, I am not sure how to pass selected booksId s from the view to the controller and use them by the borrow or Return bttons? could you please help?
Here is my Html file https://wtools.io/paste-code/b5g4
and this is the relevant part from my bookService implementation :
public void borrowBook(String userEmail, String bookIds, Model model) {
if (!CollectionUtils.isEmpty(books)) {
User user = userRepository.findByEmail(userEmail);
List<String> requestedBooks = getRequestedBookIds(bookIds);
List<Book> borrowedBooks = new ArrayList<>();
List<Book> invalidBooks = new ArrayList<>();
for (Book book : books) {
if (requestedBooks.contains(book.getId()) && !book.isBorrowed() && user != null) {
book.setBorrowed(true);
book.setBorrowedBy(user.getFirstName());
borrowedBooks.add(book);
model.addAttribute("bookStatus", "Book BOrrowed By " + user.getFirstName());
} else {
invalidBooks.add(book);
model.addAttribute("bookStatus", "No Books are available");
}
}
model.addAttribute("inValidBooks", invalidBooks);
model.addAttribute("bookList", borrowedBooks);
}
}
#SuppressWarnings("unchecked")
private List<String> getRequestedBookIds(String bookIds) {
List<String> requestedBookIds = null;
try {
requestedBookIds = new ObjectMapper().readValue(bookIds, ArrayList.class);
} catch (Exception e) {
e.printStackTrace();
}
return !CollectionUtils.isEmpty(requestedBookIds) ? requestedBookIds : new ArrayList<>();
}
and this is from the controller:
#GetMapping(value = "/available", produces = MediaType.APPLICATION_JSON_VALUE)
public String getAvailableFreeBooks(Model model) {
List<Book> availableBooks= bookService.getAllAvailaBooks();
model.addAttribute("listBooks", availableBooks);
return "available_books";
}
In your html you would probably:
<input type="checkbox" th:field="*{requestedBooks}" value="${book.getId}">
omit the id (if you don't need it).
use th:field (instead of name).
set value to the id of the current book.
In your controller: requestedBooks (#ModelAttribute("requestedBooks") List<String> requestedBooks) will (should) contain all checked book ids.
Ref: https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#checkbox-fields
A sample repository:
https://github.com/xerx593/soq67602860
Uppdate:
To process the checkboxes client-sided (jquery),
you can obtain an array of ids like:
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$("#btnBorrow").click(function() {
var reqBookIds = new Array();
$('input[name="requestedBooks"]:checked').each(function() {
reqBookIds .push(this.value);
});
alert("Number of selected Books: "+reqBookIds .length+"\n"+"And, they are: "+reqBookIds);
// do stuff with reqBookIds ...
)};
});
</script>
With the mentioned <input type="checkbox" .../> (consider that <input/> should be inside a <form/>!!) and a button like:
<button id="btnBorrow">Borrow</button>
..the userEmail must come from client side???
My model contains:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
My controller contains:
public ActionResult Index(int? personId)
{
var people = db.People; // all people in my database
ViewBag.People = new SelectList(people, "Id", "Name", personId);
return View();
}
My view contains:
#using (Html.BeginForm(null, null, FormMethod.Get, new { #class = "form-inline" }))
{
#Html.DropDownList("personId", ViewBag.People as SelectList, "All people", new { #class = "form-control select-submit" })
}
And I have this piece of Javascript:
<script type="text/javascript">
(function ($) {
$(".select-submit").change(function () {
$(this).parents("form").submit();
alert("form submitted!");
});
})(jQuery);
</script>
When I select a person from the DropDownList, I see the alert popup, and the page refreshes. When I select the default option ("All People"), I also see the popup, but the page does not refresh.
I want "personId" to be set to "" on selecting the default option. How can I achieve this?
Ah, I found it. After inspecting the html, I noticed the form was using data validation. These html attributes were getting added after selecting a person:
data-val="true" data-val-number="The field Int32 must be a number." data-val-required="The Int32 field is required."
The form couldn't be submitted because "" is not valid for an Int32. Adding this html attribute to the DropDownList solved it:
data_val = false
I want to receive json object from view to controller using $.ajax method but i dont know why the receive object in controller shows null data.
here is my code.
$("#Save").click(function (e) {
$.ajax({ url: "Home/Save",
type: "POST",
datatype:'json',
data: ({movies:movies})
});
});
where movies is javascript array which contains
({
Name:"DDLJ",Stars:"SRK",Director:"Yashraj",Year:"2012"
}, {Name:"K3G",Stars:"SRK",Director:"Karan",Year:"2010"}
)
and my controller code is:
public string Save (List<MovieDB> movies)
{
return "";
}
where MovieDB is my model class which have the properties
public class MoviesDB
{
//public int MoviesID { get; set; }
public string Name { get; set; }
public string Stars { get; set; }
public string Director { get; set; }
public DateTime Year { get; set; }
}
Please suggest me any better way to receive json data from view to controller.
Actully I try to send javascript array object from view to controller action method in which my array code is
<script type="text/javascript">
var cnt = 1;
var cnt2 = 1;
var i;
var movies = [];
movies.push({ Name: $("#txtMovieName").val(), Stars: $("#txtStarCasts").val(), Director: $("#txtDirector").val(), Year: $("#txtYear").val(), Index: cnt++ });
$("#modelTable").empty();
$("#modelTemplate").tmpl(movies).appendTo($("#modelTable"));
$("#txtMovieName").val("");
$("#txtStarCasts").val("");
$("#txtDirector").val("");
$("#txtYear").val("");
$("#txtMovieName").focus();
e.preventDefault();
});
$("#Save").click(function (e) {
//var jm = $.toJSON(movies);
$.ajax({ url: "Home/Save",
type: "POST",
data: ({movies:movies})
// contentType: 'application/json; charset=utf-8'
});
});
</script>
Now I want to send that movies javascript array object to Save() Action method of controller using any way like json or other please suggest me something...
This is not a correct json. You can check this on JSONLint
Here is the correct json:
[
{
"Name": "DDLJ",
"Stars": "SRK",
"Director": "Yashraj",
"Year": "2012"
},
{
"Name": "K3G",
"Stars": "SRK",
"Director": "Karan",
"Year": "2010"
}
]
If there are still errors, let me know.
Maybe this is a better answer, if you want to get your data into your controller after a post.
//For going to your view.
public ActionResult Create()
{
MoviesDB model = new MoviesDB();
return View("Create", model);
}
[HttpPost]
public ActionResult Create(MoviesDB model)
{
if (ModelState.IsValid)
{
//Here you can use your model param
//with the filled in values of your view.
return RedirectToAction("Index");
//when everything works fine, go to this view.
}
else
{
return RedirectToAction("Index");
//when there is a problem, go to this view.
}
return View("Index");
}
You don't need jQuery to use your data from your view.
List<xyztype> lstid = new JavaScriptSerializer().Deserialize<List<xyztype>>(IDlist);
is working for me
here xyztype is my collection class type and IDlist is my json objectstring from view to controller action method
by using javascriptserializer().deserializer<> we can convert json string to our custom or system datatype object
for example :
List<string> lstid = new JavaScriptSerializer().Deserialize<List<string>>(IDlist);
I've implemented my cascading dropdown list with MVC3 almost exactly as explained in
Easiest way to create a cascade dropdown in ASP.NET MVC 3 with C#
My view had that
<script type="text/javascript">
$(function () {
$('#CategoryID').change(function () {
var selectedCategoryId = $(this).val();
$.getJSON('#Url.Action("SelectCategory")', { categoryid: selectedCategoryId }, function (subcategories) {
var subsSelect = $('#SubCategoryID');
subsSelect.empty();
$.each(subcategories, function (index, subcat) {
subsSelect.append(
$('<option/>')
.attr('value', subcat.SubCategoryID)
.text(subcat.SubCategoryName)
);
});
});
});
});
</script>
My controller had that
public ActionResult SelectCategory(int categoryid)
{
var subs = db.SubCategories.Where(s => s.CategoryID == categoryid).ToList();
return Json(subs, JsonRequestBehavior.AllowGet);
}
And that did not work.
However, it worked when I modified the controller the following way:
public class JsonSubCat
{
public int SubCategoryID { get; set; }
public string SubCategoryName { get; set; }
}
public ActionResult SelectCategory(int categoryid)
{
var subs = db.SubCategories.Where(s => s.CategoryID == categoryid).ToList();
var testsubs = new List<JsonSubCat>();
foreach (var sub in subs)
{
testsubs.Add(new JsonSubCat() { SubCategoryID = sub.SubCategoryID, SubCategoryName = sub.SubCategoryName });
}
return Json(testsubs, JsonRequestBehavior.AllowGet);
}
Looks like a question of converting my entities that I obtain from data source to proper format.
What would be the correct way to implement this?
What would be the correct way to implement this?
I suspect that you have circular references in your domain entities. This is not supported by the JSON serializer, because the JSON format doesn't support circular structures.
You should not pass your domain models to views. Please stop doing this and use view models. Why are you passing your entire subs entity to the view when all that this view cares about is a collection of text and value? That's all a dropdown list needs.
So use view models, not to mention that you already wrote one => the JsonSubCat class which is great:
public ActionResult SelectCategory(int categoryid)
{
var subs = db.SubCategories
.Where(s => s.CategoryID == categoryid)
.ToList()
.Select(x => new JsonSubCat
{
SubCategoryID = x.SubCategoryID,
SubCategoryName = x.SubCategoryName
});
return Json(subs, JsonRequestBehavior.AllowGet);
}
I have an array of JSON objects I am posting to a MVC3 controller. The JSON seems to post fine based on the fiddler check I ran. (included below) The controller is accepting a custom class I setup to receive the JSON data. That seems to work fine as well (debugger screenshot included below) The issue is that the object properties don't seem to be autobinding like I would expect. The names all match, I'm not sure the issue.
The jquery is below (first click to add to the array, then click to post the data)
var removes = [];
var adds = [];
var transaction = {
'adds': adds,
'removes': removes
};
jQuery(".AddCardLink").click(function () {
var card = [{
Id: jQuery(this).attr("cardid"),
Name: jQuery(this).attr("cardname")
}];
transaction.adds.push(card);
})
jQuery("#btnSave").click(function () {
jQuery.ajax({
type: "POST",
url: "/SaveTransactionLog",
data: JSON.stringify(transaction),
dataType: "json",
contentType: "application/json",
success: function (data) {
alert("Test");
}
});
});
This is the fiddler view of the sent data
The custom class and controller are below:
public class Card
{
public int Id { get; set; }
public string Name { get; set; }
}
public class JsonTransaction
{
public List<Card> Adds { get; set; }
public List<Card> Removes { get; set; }
}
[HttpPost]
public JsonResult SaveTransactionLog(JsonTransaction transaction)
{
return Json()
}
Finally, here is the debugger look at the JsonTransaction, you can see the autobind setup the correct lists, but the Card in the list properties are empty.
If you stuck till the end, thanks! Any help would be great!
Argh! After spending the whole weekend on this and finally posting on SO yesterday, I discovered my issue!
My Jquery I had an extra square bracket around my objects when I was adding them through onclick. Removing the square brackets solved my issue.
jQuery(".AddCardLink").click(function () {
var card = **[**{
Id: jQuery(this).attr("cardid"),
Name: jQuery(this).attr("cardname")
}**]**;
transaction.adds.push(card);
})