How to append DDL during AJAX call - javascript

I'm trying to alter the value of a drop down list whenever the partial view is called. At the moment the AJAX call retrieves the information i need, but the user has to alter the location value in the partial view before saving, basically i want the value of location to be changed during the ajax call, thus saving the user time on altering the value by hand, i've attempted it but clearly doesn't work (see the code below), any ideas on where im going wrong?
_CameraInfo.cshtml (partial view)
#model JobTracker.Models.Job
<h2>Edit and Confirm</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Job</legend>
#Html.HiddenFor(model => model.JobID)
#Html.HiddenFor(model => model.OrderID)
<div class="editor-label">
#Html.LabelFor(model => model.LocationID, "Location")
</div>
<div class="editor-field">
#Html.DropDownList("LocationID", null, new {id ="Location" })
#Html.ValidationMessageFor(model => model.LocationID)
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.HighPriority)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.HighPriority, new SelectList(
new[]
{
new { Value = "Yes", Text = "Yes" },
new { Value = "No", Text = "No" },
},
"Value",
"Text",
Model
))
#Html.ValidationMessageFor(model => model.HighPriority)
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.Comments)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Comments)
#Html.ValidationMessageFor(model => model.Comments)
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.Status)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Status, new SelectList(
new[]
{
new { Value = "In Progress", Text = "In Progress" },
new { Value = "Completed", Text = "Completed" },
new { Value = "Not Started", Text = "Not Started" },
new { Value = "Stopped", Text = "Stopped" },
},
"Value",
"Text",
Model
))
#Html.ValidationMessageFor(model => model.Status)
</div><br />
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
AJAX call
$(document).ready(function () {
$('#qr-number').on('change', function () {
var ddl = $('#Location');
var value = "cleanroom";
$.ajax({
type: "Get",
url: '/CameraInfo/Edit',
data: { ID: $('#qr-number').val() },
success: function (response) {
ddl.append(value);
$('#Sample').html(response);
},
error: function (response) {
if (response.responseText != "") {
alert(response.responseText);
alert("Some thing wrong..");
}
}
});
});
});
});
The DDL is populated by the model data by the way.
Please let me know if you require any further information :)

for ddl value
ddl.val(value);
for ddl text
ddl.text(value);
use .val() or .text() not .append()

Related

Cascading population of a mvc dropdown

I have 2 DropDowns in an MVC application. Trying to populate the second one based on the first one's chosen value (Cascading)..
Since I am rather new to MVC this is giving me a little problem..
This is how ot looks in my View..
I am getting the data based on the selection in the first DropDown
This is the JS code for retriving the data..
<script type="text/javascript">
$('#AllShips').change(function () {
var selectedShip = $("#AllShips").val();
console.log(selectedShip);
var arrivalSelect = $('#AllShipArrivals');
arrivalSelect.empty();
if (selectedShip != null && selectedShip != '') {
$.getJSON('#Url.Action("GetArrivals")', { ShipID: selectedShip }, function (arrivals) {
console.log(arrivals);
if (arrivals != null && !jQuery.isEmptyObject(arrivals))
{
arrivalSelect.append($('<option/>', {
value: null,
text: ""
}));
$.each(arrivals, function (index, arrival) {
console.log(arrival.Value);
console.log(arrival.Text);
arrivalSelect.append($('<option/>', {
value: arrival.Value,
text: arrival.Text
}));
});
};
});
}
});
Here is my HTML
<div class="col-lg-2 form-group">
#Html.LabelFor(model => model.AllShips, htmlAttributes: new { #class = "control-label col-md-12" })
<div class="col-md-12">
#if (Model.AllShips != null)
{
#Html.DropDownListFor(model => model.ShipID, Model.AllShips, new { #class = "form-control", id = "AllShips" })
#Html.ValidationMessageFor(model => model.ShipID, "", new { #class = "text-danger" })
}
</div>
</div>
<div class="col-lg-2 form-group">
#Html.LabelFor(model => model.AllShipArrivals, htmlAttributes: new { #class = "control-label col-md-12" })
<div class="col-md-12">
#if (Model.AllShipArrivals != null)
{
#Html.DropDownListFor(model => model.ArrivalId, Model.AllShipArrivals, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ArrivalId, "", new { #class = "text-danger" })
}
else
{ #Html.DropDownListFor(model => model.ArrivalId, null, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ArrivalId, "", new { #class = "text-danger" })}
</div>
</div>
Still the second DropDown is not changing (initially I populate it with a list of all Arrivals, yes I know..not a good option)
Any idea what I am doing wrong here??
Thanks for the HTML, it is what I suspected. In your JS your are referencing 2nd DDL by var arrivalSelect = $('#AllShipArrivals'); but there is no such element (it is, but this is just a label), instead you should use:
var arrivalSelect = $('#ArrivalId');
Make 'PartialView' or 'ViewComponent' for the second Dropdown, do ajax call on changing selection in the first dropdown, choose data depending on the value you passed during the ajax call, pass the data into your partial view and return it.
Something like
public IActionResult SecondDropdownPartial(int selectedShip)
{
var data = GetSomeData(selectedShip);
return Partial("ViewName", data);
}
In js 'success' you get your view in response. Replace it on the page with
$('#container').html(response);
for example.
More information : Rendering Partial Views using ajax
edited
try making the value to be empty string rather than null
emptyStr="";
arrivalSelect.append('<option value="${emptyStr}"> ${emptyStr} </option>');
arrivalSelect.append('<option value="${arrival.Value}"> ${arrival.Text} </option>');

How to pass data from a form to my controller, and then back to my client-side javascript?

I have a form in my webpage that asks for first and last name. When the user submits this form I would like the data to be passed to a function in my controller, where it is used to find the corresponding user in our Active Directory. I want to then return the matching Email address to a Javascript function, when then displays that information on my page. Is this the "correct" way to go about doing this, and if yes, how would I structure a function in my controller to accept form input, and return data to my client side javascript?
What I have so far in my controller:
public SearchResult[] searchAD(String fname, String lname)
{
Func<System.DirectoryServices.ActiveDirectory.Domain> domain = System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain;
System.DirectoryServices.DirectoryEntry root = new DirectoryEntry("LDAP://"+domain);
DirectorySearcher searcher = new DirectorySearcher();
searcher.SearchRoot = root;
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = string.Format("(&(objectCategory=person)(objectClass=user)(givenName={0})(sn={1}))", fname, lname);
SearchResult[] results = new SearchResult['a'];
searcher.FindAll().CopyTo(results, 0);
return results;
}
And my form:
#using (Html.BeginForm("searchAD", "AD", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.firstName, "First Name", htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.firstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.firstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.lastName, "Last Name", htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.lastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.lastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div>
<input type="submit" value="Search" class="btn" />
</div>
</div>
}
You can Store value in TempData and get it on view
public ActionResult searchAD(String fname, String lname)
{
Func<System.DirectoryServices.ActiveDirectory.Domain> domain = System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain;
System.DirectoryServices.DirectoryEntry root = new DirectoryEntry("LDAP://"+domain);
DirectorySearcher searcher = new DirectorySearcher();
searcher.SearchRoot = root;
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = string.Format("(&(objectCategory=person)(objectClass=user)(givenName={0})(sn={1}))", fname, lname);
SearchResult[] results = new SearchResult['a'];
searcher.FindAll().CopyTo(results, 0);
TempData["Result"]=results;
return View("ViewName");
}
In View (Jquery)
$(function(){
if ('#TempData["Result"]' != '')
{
// call your function here and pass TempData Value
}
});
Above is not perfect solution for your posted issue because tempdata or viewbag are not meant for that.If you need to post data again back from control to view then its always make use of #Ajax.BeginForm
#using (Ajax.BeginForm("ActionName", "Controller", new AjaxOptions { OnComplete = "Sucess" }))
in jquery you have to write Success function like below :
function Sucess(arg) {
//arg.data
}
in arg.data you will get that object what you are passing from controller.More ever #Html.BeginForm refreshing your whole page not specific content but with With Ajax.begin form you can manage to reload only those content which is under ajax.begin form.

MVC - jQuery validation does not work on dynamically added elements

I know this kind of issue has been solved many times already, however I am unable to get mine fixed based on solutions provided.
I am building a simple library application. There is a feature to add a copy of a book, which uses jQuery to invoke controller actions and return partial views which are then added dynamically to the DOM.
The last dynamically element added is a form with additional details of a created copy. The ajax call is being triggered when a value of a DropDownList (#AuthorBooksDropDown) (also added dynamically) changes.
$('#authorBooksPlaceHolder').on('change', '#AuthorBooksDropDown', function () {
var bookId = $(this).val();
$.get('/Books/AddCopy_RenderDetails/' + bookId, function (data) {
$('#bookDetailsPlaceHolder').html(data);
$('#bookDetailsPlaceHolder').slideDown();
});
$.validator.unobtrusive.parse('#addCopyForm');
});
The call invoked the AddCopy_RenderDetails action get an entity from a DB based on book id, and creates a new copy with certain fields populated.
Controller action:
public PartialViewResult AddCopy_RenderDetails(int id)
{
var book = db.LibraryBooks.Find(id);
var newCopy = new Book()
{
Author = book.Author,
Title = book.Title,
Publisher = book.Publisher,
CollectionId = book.CollectionId,
Collection = book.Collection
};
return PartialView("_AddCopy_Details", newCopy);
}
The view displays remaining fields which need to be populated.
#model CityLibrary.Models.Library.Book
<div class="vertical-separator"></div>
<hr />
#using (Ajax.BeginForm("AddCopy", "Books", new AjaxOptions
{
UpdateTargetId = "bookDetailsPlaceHolder"
}, new { #id = "addCopyForm" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.Author)
#Html.HiddenFor(model => model.Title)
#Html.HiddenFor(model => model.CollectionId)
#Html.HiddenFor(model => model.Collection.Name)
#Html.HiddenFor(model => model.Publisher)
<div class="form-group">
#Html.LabelFor(model => model.Collection.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Collection.Name, new { htmlAttributes = new { #class = "form-control", #disabled = "" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ISBN, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ISBN, new { htmlAttributes = new { #class = "form-control", } })
#Html.ValidationMessageFor(model => model.ISBN, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Publisher, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Publisher, new { htmlAttributes = new { #class = "form-control", #disabled = "disabled" } })
#Html.ValidationMessageFor(model => model.Publisher, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.YearPrinted, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.YearPrinted, new { htmlAttributes = new { #class = "form-control", #Value = "" } })
#Html.ValidationMessageFor(model => model.YearPrinted, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-success btn-block" />
</div>
</div>
}
Even though I have $.validator.unobtrusive.parse('#addCopyForm'); invoked when the form is rendered (checked in chrome dev tools), validation still happens on the server side upon pressing a submit button as a POST action is being triggered every time. Not to mention that validation errors do not display upon TABing to next field.
Validation attributes are there in form's inputs:
I also have remote validation which checks whether a entered ISBN is already in the database. Obviously this works on the client side, which in my case simply does not.
Thank you for your time and help.
EDIT:
Well, I've added the following to the end of the view:
<script>
$.validator.unobtrusive.parse('#addCopyForm');
</script>
And it works. I have no idea why triggering it on a function does nothing.
Ajax is async, and your $.validator.unobtrusive.parse('#addCopyForm'); line of code is being called before the html has been added to the DOM. Move it to inside the success callback
$.get('/Books/AddCopy_RenderDetails/' + bookId, function (data) {
$('#bookDetailsPlaceHolder').html(data);
$('#bookDetailsPlaceHolder').slideDown();
$.validator.unobtrusive.parse('#addCopyForm');
});
Try this peace of code
$("form").on("submit", function (e) {
e.preventDefault();
$.validator.unobtrusive.parse($('#addCopyForm')); // here you need define your form id
if ($(this).valid()) // use to validate the form
{
//do ajax call
$.ajax({
type: "Post",
url: "/Books/AddCopy_RenderDetails/" + bookId,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
}
});
}
});

ASP.NET MVC jQuery JSON result redirecting URL

Using MVC/Json/Jquery.
Using form to create a new "group".
Form is on ~Group/Manage, posting form to ~Group/Create
Whilst working on this, returning Json result was working fine, handling in Jquery, no URL redirection.
Now, everytime I run it, it redirects me to ~Group/Create and displays the Json result.
Controller Group/Create
[HttpPost]
public ActionResult Create([Bind(Include="name,description")] GroupModel groupmodel)
{
...
return Json(new { success = true, message = groupmodel.name }, JsonRequestBehavior.AllowGet);
}
Form
<form id="frm_createGroup" action="/Groups/Create" method="post">
<h2>Create Group</h2>
<div class="form-group">
#Html.LabelFor(model => model.name, new { #for = "name" })
#Html.TextBoxFor(model => model.name, new { #class = "form-control", #placeholder = "Group Name" })
#Html.ValidationMessageFor(model => model.name)
</div>
<div class="form-group">
#Html.LabelFor(model => model.description, new { #for = "description" })
#Html.TextBoxFor(model => model.description, new { #class = "form-control", #placeholder = "Group Description" })
#Html.ValidationMessageFor(model => model.description)
</div>
<span id="createGroupMessage"></span>
<button type="submit" class="btn btn-primary pull-right">Create</button>
</form>
Jquery to handle form
$(document).ready(function (){
$('#navGroups').makeActiveMenuItem();
var options = {
success: groupCreateSubmitted
,error: groupCreateError
}
$('#frm_createGroup').ajaxForm(options);
});
function groupCreateSubmitted(responseText, statusText, xhr, $form) {
if (responseText.success)
{
$('#createGroupMessage').html = "Group Created";
}
else
{
$('#createGroupMessage').html = responseText.message;
}
}
To be clear, I don't want URL redirection, I just want the Jquery to catch the return (it was before, have no idea why its changed...)
Thanks!
removed
,error: groupCreateError
working now...form bind was failing.

How to pass value to controller and partial view via JS

I'm trying to implement a system where the value within a text box is passed onto a partial view, where it will present the details corresponding to that value. So for instances if Job "1" was within the text box , the partial view will return the details of that job for the user to change etc. Any Ideas on how to pass the value to the controller then the partial view?
Job.js
$(document).ready(function () {
$('#qr-value').on('change', function () {
if ($('#qr-value').val() == 'Job 1') {
$("#second").show(1000);
}
});
});
CameraInfo (partial view)
model JobTracker.Models.Job
<h2>Edit and Confirm</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Job</legend>
#Html.HiddenFor(model => model.JobID)
<div class="editor-label">
#Html.LabelFor(model => model.OrderID, "Order")
</div>
<div class="editor-field">
#Html.DropDownList("OrderID", String.Empty)
#Html.ValidationMessageFor(model => model.OrderID)
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.LocationID, "Location")
</div>
<div class="editor-field">
#Html.DropDownList("LocationID", String.Empty)
#Html.ValidationMessageFor(model => model.LocationID)
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.HighPriority)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.HighPriority, new SelectList(
new[]
{
new { Value = "Yes", Text = "Yes" },
new { Value = "No", Text = "No" },
},
"Value",
"Text",
Model
))
#Html.ValidationMessageFor(model => model.HighPriority)
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.Comments)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Comments)
#Html.ValidationMessageFor(model => model.Comments)
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.Status)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Status, new SelectList(
new[]
{
new { Value = "In Progress", Text = "In Progress" },
new { Value = "Completed", Text = "Completed" },
new { Value = "Not Started", Text = "Not Started" },
new { Value = "Stopped", Text = "Stopped" },
},
"Value",
"Text",
Model
))
#Html.ValidationMessageFor(model => model.Status)
</div><br />
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to Home Page", "Index","Home")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Job Controller.cs
//
// GET: /Job/Edit/5
public ActionResult Edit(int id = 0)
{
Job job = db.Jobs.Find(id);
if (job == null)
{
return HttpNotFound();
}
ViewBag.LocationID = new SelectList(db.Locations, "LocationID", "LocationName", job.LocationID);
ViewBag.OrderID = new SelectList(db.Orders, "OrderID", "OrderID", job.OrderID);
return View(job);
}
//
// POST: /Job/Edit/5
[HttpPost]
public ActionResult Edit(Job job)
{
if (ModelState.IsValid)
{
db.Entry(job).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.LocationID = new SelectList(db.Locations, "LocationID", "LocationName", job.LocationID);
ViewBag.OrderID = new SelectList(db.Orders, "OrderID", "OrderID", job.OrderID);
return View(job);
}
<div id='Sample'></div>
if you want to load the partial view use ajax.
$(document).ready(function () {
$('#qr-value').on('change', function () {
$.ajax({
type: "Get",
url: '#Url.Action("Edit", "job")',
data: { id: $('#qr-value').val()},
success: function (response) {
$('#Sample').html(response);
},
error: function (response) {
if (response.responseText != "") {
alert(response.responseText);
alert("Some thing wrong..");
}
}
});
});
});
[HttpGet]
public ActionResult Edit(int id = 0)
{
Job job = db.Jobs.Find(id);
if (job == null)
{
return HttpNotFound();
}
ViewBag.LocationID = new SelectList(db.Locations, "LocationID", "LocationName", job.LocationID);
ViewBag.OrderID = new SelectList(db.Orders, "OrderID", "OrderID", job.OrderID);
return PartialView("Edit",job);
}
Hope this helps

Categories