I am new to MVC and very new to jQuery. I am trying to populate text boxes in a partial view using jQuery that resides in the parent view. The relevant sections of the parent view are as follows:
@{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
function RemoveRow() {
var $tr = $(this).closest('#row');
$tr.remove();
}
</script>
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Quote</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.QuoteId)
<div class="form-group">
@Html.LabelFor(model => model.CustomerId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.CustomerId, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.CustomerId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@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(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@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">
@Html.LabelFor(model => model.Company, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Company, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Company, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Subtotal, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Subtotal, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Subtotal, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Tax, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Tax, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Tax, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Total, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Total, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Total, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.QuoteDetail, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10" id="QuoteDetails">
@for (int i = 0; i < Model.QuoteDetail.Count; i++)
{
<div id="row">
@Html.EditorFor(model => model.QuoteDetail[i].QuoteId, new { htmlAttributes = new { @class = "form-control" } })
@Html.EditorFor(model => model.QuoteDetail[i].QuoteDetailId, new { htmlAttributes = new { @class = "form-control" } })
@Html.HiddenFor(model => model.QuoteDetail[i].ProductId, new { htmlAttributes = new { @class = "form-control" } })
@Html.EditorFor(model => model.QuoteDetail[i].ProductName, new { htmlAttributes = new { @class = "form-control" } })
@Html.EditorFor(model => model.QuoteDetail[i].Amount, new { htmlAttributes = new { @class = "form-control" } })
@Html.EditorFor(model => model.QuoteDetail[i].ListPrice, new { htmlAttributes = new { @class = "form-control" } })
@Html.EditorFor(model => model.QuoteDetail[i].Discount, new { htmlAttributes = new { @class = "form-control" } })
@Html.EditorFor(model => model.QuoteDetail[i].Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.QuoteDetail, "", new { @class = "text-danger" })
@Ajax.ActionLink(" ", "DeleteProduct", "QuoteViewModel", new { quoteId = Model.QuoteDetail[i].QuoteId, quoteDetailId = (Model.QuoteDetail[i].QuoteDetailId) },
new AjaxOptions
{
HttpMethod = "POST",
Confirm = "Are you Sure You Want to Delete " + Model.QuoteDetail[i].ProductName,
//OnSuccess = "function() { window.location.reload(); }"
OnSuccess = "RemoveRow"
},
new { @class = "btn btn-danger glyphicon glyphicon-trash" })
</div>
}
@Ajax.ActionLink("Add product", "AddProduct", "QuoteViewModel", new { quoteId = Model.QuoteId, quoteDetailId = (Model.QuoteDetail.Count + 1) }, new AjaxOptions
{
UpdateTargetId = "QuoteDetails",
InsertionMode = InsertionMode.InsertAfter
})
<p> </p>
</div>
<script type="text/javascript">
$(document).ready(function () {
alert("Step 1");
$('[id*="ProductList"]').change(function () {
alert("We got this far");
$.post("/QuoteViewModel/GetProduct", { pId: $(this).val() }, function (data) {
alert("Did we get this far?")
$("[id*='ProductId']").val(data.ProductId);
$("[id*='Price']").val(data.Price);
});
});
});
</script>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
The partial view is as follows:
@model CMSUsersAndRoles.Models.QuoteDetail
@{
ViewBag.Title = "EditQuoteDetail";
Layout = null;
}
@{
var quoteId = (int)ViewData["QuoteId"];
var quoteDetailId = (int)ViewData["QuoteDetailId"];
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
</head>
<body>
<div id="row">
<table>
@using (Html.BeginCollectionItem("quoteDetail"))
{
<tr>
@Html.HiddenFor(model => model.QuoteId, new { htmlAttributes = new { @class = "form-control" } })
@Html.HiddenFor(model => model.QuoteDetailId, new { htmlAttributes = new { @class = "form-control" } })
@Html.TextBoxFor(model => model.ProductId, new { htmlAttributes = new { @id = "ProductId", @class = "form-control" } })
@Html.DropDownList("ProductList", new SelectList(ViewBag.ProductData, "ProductId", "Name"), new { htmlAttributes = new { @id = "ProductList", @class = "form-control" } });
@Html.EditorFor(model => model.Amount, new { htmlAttributes = new { @class = "form-control" } })
@Html.TextBoxFor(model => model.Price, new { htmlAttributes = new { @id = "Price", @class = "form-control" } })
@Html.EditorFor(model => model.Discount, new { htmlAttributes = new { @class = "form-control" } })
@Html.EditorFor(model => model.ListPrice, new { htmlAttributes = new { @class = "form-control" } })
@Ajax.ActionLink(" ", "DeleteProduct", "QuoteViewModel", new { quoteId = Model.QuoteId, quoteDetailId = (Model.QuoteDetailId) },
new AjaxOptions
{
HttpMethod = "POST",
Confirm = "Are you Sure You Want to Delete " + Model.ProductName,
OnSuccess = "RemoveRow"
},
new { @class = "btn btn-danger glyphicon glyphicon-trash" })
</tr>
}
</table>
</div>
</body>
</html>
The jQuery at the bottom of the Edit view is what I'm concerned about, namely:
<script type="text/javascript">
$(document).ready(function () {
alert("Step 1");
$('[id*="ProductList"]').change(function () {
alert("We got this far");
$.post("/QuoteViewModel/GetProduct", { pId: $(this).val() }, function (data) {
alert("Did we get this far?")
$("[id*='ProductId']").val(data.ProductId);
$("[id*='Price']").val(data.Price);
});
});
});
</script>
I put the alerts in the javascript because I wanted to see how far I was getting in the code. The "Step 1" alert fires, but nothing beyond that. The BeginCollectionItem helper in the partial view adds what appear to be guids to the ID and Class ProductList and ProductId, e.g., quoteDetail_2b71523b-3714-4e0d-bb83-e8fbb3b3a7fb__ProductList. For this reason I altered the jQuery to select ids which contain, e.g., "ProductList". Still, the jQuery does not fire on the change event. Any help would be much appreciated.
Per request below, here is part of the rendered HTML:
<select htmlattributes="{ id = ProductList, class = form-control }" id="quoteDetail_f13ff5a1-6705-44f0-957a-0b739c5cfa53__ProductList" name="quoteDetail[f13ff5a1-6705-44f0-957a-0b739c5cfa53].ProductList"><option value="1">Albi Polymer</option>
<option value="2">Fireproofing Paint</option>
</select>
Per suggestion below, I changed the jQuery as follows:
<script type="text/javascript">
$(document).ready(function () {
alert("Step 1");
$('#QuoteDetails').on('change', 'ProductList', function() {
alert("We got this far");
$.post("/QuoteViewModel/GetProduct", { pId: $(this).val() }, function (data) {
alert("Did we get this far?")
$("[id*='ProductId']").val(data.ProductId);
$("[id*='Price']").val(data.Price);
});
});
});
</script>
I added the class "ProductList" to the dropdownlist as follows:
@Html.DropDownList("ProductList", new SelectList(ViewBag.ProductData, "ProductId", "Name"), new { htmlAttributes = new { @id = "ProductList", @class = "ProductList" } });