Assign default selection from dropdown to model class within another model - c#

Here is some of the relevant code right away
Markup
<div class="well">
<input type="button" id="addNewCert" value="Add New Certification" class="btn btn-primary" data-bind="click: addCert"/>
</div>
<table class="table table-striped">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Code</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody data-bind="foreach: certs">
<tr>
<td>Edit</td>
<td>Delete</td>
<td data-bind="text: certName"></td>
<td data-bind="text: certCode"></td>
<td data-bind="text: description"></td>
<td data-bind="text: certType.certTypeName"></td>
</tr>
</tbody>
</table>
<div id="selectedCert" data-bind="with: selectedCert">
<div class="well">
<div class="row-fluid">
<div class="span6">
<div class="control-group">
<h6>Certification Name</h6>
<input type="text" id="CertificationName" data-bind="value: certName" style="width:100%;" />
</div>
<div class="control-group">
<h6>Certification Code</h6>
<input type="text" id="CertificationCode" data-bind="value: certCode" style="width:50%;" />
</div>
<div class="control-group">
<h6>Description</h6>
<textarea ID="Description" data-bind="value: description" style="height:250px;width:480px;"></textarea>
</div>
<div class="control-group">
<h6>Certification Type</h6>
<select id="CertificationType" data-bind="options: $parent.availableCertTypes, optionsText: 'certTypeName', optionsValue: 'certTypeId', value: $parent.selectedCertType" style="width:100%;"></select>
</div>
<div class="control-group">
<button class="btn btn-primary" data-bind="click: $parent.save">Save</button>
<button class="btn" data-bind="click: $parent.cancel">Cancel</button>
</div>
</div>
</div>
</div>
</div>
ViewModel
//Bound to a dropdown and populated by an ajax call listed below
self.availableCertTypes = ko.observableArray([]);
self.selectedCert = ko.observable();
self.addCert = function () {
self.selectedCert(new Certification({});
//This line doesn't work :(
//self.selectedCert(new Certification(self.availableCertTypes()[0]));
};
//Populates availableCertTypes
$.getJSON(sf.getServiceRoot('InCertModule') + 'InCert/GetCertTypesByPortal', function (data) {
//Could call 'self.Certs(self.MapItems(data))' here as that would take the fetched data and populate the viewModel's list of certifications used for binding
var mappedCertTypes = $.map(data, function (item) {
return new CertType(item);
});
self.availableCertTypes(mappedCertTypes);
});
Models
var Certification = function (data) {
if (!data) {
//If there is no data, pass an empty intialized object, otherwise get an undefined reference
data = {};
} else {
this.certId = ko.observable(data.CertificationId);
this.certName = ko.observable(data.CertificationName);
this.certCode = ko.observable(data.CertificationCode);
this.description = ko.observable(data.Description);
this.certType = ko.observable(new CertType(data));
//this.certTypeId = ko.observable(data.CertTypeId);
//this.certTypeName = ko.observable(data.CertTypeName);
this.isEditing = ko.observable(false);
this.isValid = ko.observable(true);
}
}
var CertType = function (data) {
this.certTypeId = ko.observable(data.CertTypeId);
this.certTypeName = ko.observable(data.CertTypeName);
}
I also have an edit function set up with a with binding. This works correctly and gets my CertType model nested properly, like so
"selectedCert": {
"certId": 10,
"certName": "AFC Service Training",
"certCode": "AFCST",
"description": "The training required to work AFC service",
"certType": {
"certTypeId": 1,
"certTypeName": "Certification"
},
"isEditing": false,
"isValid": true
},
However, I've tried a few combinations for my addCert function to take the very first item in the availableCertTypes ObservableArray and assign it. Reason being is when I post it to my web service, I need to ensure that something is selected there.
I'm new to Knockout.js so not even sure what's possible or how to really accomplish it but ideally when I call addCert, I'd like to see something similar to this
"selectedCert": {
//The first item in the observable array
"certType": {
"certTypeId": 1,
"certTypeName": "Certification"
},
"isEditing": false,
"isValid": true
}
but instead I wind up with
"selectedCert": {
"certType": {},
"isEditing": false,
"isValid": true
}
If I need to post more code I can, just let me know. Any help is greatly appreciated.
Edit Here is a jsFiddle with most of the markup, although it's not working? http://jsfiddle.net/jtCrw/1/
The array binds correctly when fetched from the web service, just not sure how to hard code those in there. Currently those 2 are the only two options.

The root of your empty certType problem is due to a mismatch/typo in your setup.
self.addCert = function () {
self.selectedCert(new Certification(self.availableCertTypes()[0]));
}
resulting in an eventual call to this.certType = ko.observable(new CertType(data));
var CertType = function (data) {
this.certTypeId = ko.observable(data.CertTypeId); //expecting uppercase property
this.certTypeName = ko.observable(data.CertTypeName);
}
self.availableCertTypes = ko.observableArray([
{
"certTypeId": 1, //data-bind and this declaration are both lowercase
"certTypeName": "Certification"
},
{
"certTypeId": 2,
"certTypeName": "Training"
}
]);
fixing that yields the expected result from your current setup
"selectedCertType":{"CertTypeId":1,"CertTypeName":"Certification"}
To get the desired outcome as you have shown/requested, remove the optionsValue from the select binding and bind the value to the certType of the selected certification (provided by the with binding)
<select id="CertificationType"
data-bind="options: $parent.availableCertTypes,
optionsText: 'CertTypeName',
value: certType"
style="width:100%;"></select>
Result:
"selectedCert":{"certType":{"CertTypeId":1,"CertTypeName":"Certification"},"isEditing":false,"isValid":true}
Consideration: If you want to populate the select with data from an existing certification, some special consideration is needed. Take a look at examples of initialization.

Related

Reload Jquery DataGrid Table - not working

I have little to no experience working with jQuery or JSON. However, I found a great little tutorial online that walked me through the steps of creating a jQuery DataGrid Table - which was exactly what I needed. And it works great.
Problem is, I need to reload the table at times. And that, I cannot get working.
Here is my Controller
public ActionResult AddSupplies()
{
var q = db.ICS_Orders;
return View(q);
}
Here is my Partial View with DataGrid
l IEnumerable<ICS20web.Models.ICS_Orders>
#{
Layout = null;
}
<div id="divSupplies">
<h3>Monthly Requisition: Supplies and Forms</h3>
<div class="row">
<div class="col-md-12">
<div class="panel panel-primary list-panel" id="list-panel">
<div class="panel-heading list-panel-heading">
<h1 class="panel-title list-panel-title">Requested Supplies</h1>
</div>
<div class="panel-body">
<table id="supplies-data-table"
class="table table-striped table-bordered"
style="width:100%">
<thead>
<tr>
<th>Requisition Number</th>
<th>Supplies</th>
<th>Amount Ordered</th>
</tr>
</thead>
<tbody>
#*#foreach (var asset in Model)*#
#foreach (var asset in Model.Where(w => w.RequisitionNumber == ViewBag.TransNum))
{
<tr>
<td>#asset.RequisitionNumber</td>
<td>#asset.Supply</td>
<td>#asset.UnitsOrdered</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
<hr />
<!-- Add Java Script-->
#Scripts.Render("~/Scripts/jquery-1.10.2.min.js")
#Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.js")
#Scripts.Render("~/Scripts/CheckContacts.js")
#Scripts.Render("~/Scripts/Supplies.js")
<script type="text/javascript">
$(document).ready(function () {
$('#supplies-data-table').DataTable();
});
All of my research shows that the proper way to reload the table is with:
$('#supplies-data-table').DataTable().ajax.reload();
But this does not work. I get the following JSON error
"DataTables warning: table id=supplies-data-table - invalid JSON response.
I can't seem to find anything that helps me understand why, or how to resolve it. I am puzzled that the table will load the first time, and load on post back properly. But when forcing to reload - I get this error and it fails.
As recommended, I reconfigured the code to load the table from ajax source. I guess, I didn't fully understand how jQuery DataTables work. After reading the comments, I did some further research online and figured things out. Here is what I did
View where Table is located
<!-- Begin Jquery DataTable-->
<div class="row">
<div class="col-md-12">
<div class="panel panel-primary list-panel" id="list-panel">
<div class="panel-heading list-panel-heading">
<h1 class="panel-title list-panel-title">Requested Supplies</h1>
</div>
<div class="panel-body">
<table id="myTable" class="table table-striped table-bordered" style="width:100%">
<thead>
<tr>
<th>Requisition Number</th>
<th>Supply Name</th>
<th>Amount Requested</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>
<!-- End Jquery DataTable-->
My Jquery to Load The Table (on document.ready)
$('#myTable').DataTable({
"ajax": {
"url": "/ICSNewOrders/loaddata",
"type": "GET",
"datatype": "json"
},
"columns": [
{ "data": "RequisitionNumber", "autoWidth": true },
{ "data": "Supply", "autoWidth": true },
{ "data": "UnitsOrdered", "autoWidth": true }
]
});
});
My loaddata from my controller
public ActionResult loaddata()
{
ViewBag.TransNum = TempData["ReqNo"];
TempData.Keep();
String ReqID = Convert.ToString(TempData["ReqNo"].ToString());
using (ICSContext dc = new ICSContext())
{
dc.Configuration.LazyLoadingEnabled = false;
var data = dc.ICS_Orders.Where(s => s.RequisitionNumber == ReqID).OrderBy(a => a.RequisitionNumber).ToList();
return Json(new
{
data = data
}, JsonRequestBehavior.AllowGet);
}
}
And finally, to refresh the Jquery DataTable . . .
$('#myTable').DataTable().ajax.reload();
All works now.

View not refreshing following post in Razor MVC using datatable

As per subject. The view looks like this.
#using System.Globalization
#model IEnumerable<TaskEngine.WebUI.Models.TaskViewModel>
<script src="../../Scripts/progress-task.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
url: '#Url.Action("Index", "Home")',
data: { from: "10/01/2014", to: "10/14/2014" },
dataType: "html",
success: function () {
alert('Success');
},
error: function (request) {
alert(request.responseText);
}
});
});
</script>
<div class="container">
<div class="row">
<div class="span16">
<div id="sitename">
xxxxxxxx
<span class="name">Workbasket</span>
</div>
<div class="row">
<div class="span16">
<table class="table table-striped table-condensed" id="task-table">
<thead>
<tr>
<th class="left">Client</th>
<th class="left">Task</th>
<th class="left">State</th>
<th class="left">Assigned By</th>
<th class="left">Assigned To</th>
<th class="left">Date Opened</th>
<th class="left">Date Due</th>
#* <th class="left">Date Closed</th>*#
<th class="left">Outcomes</th>
</tr>
</thead>
<tbody>
#foreach (var task in Model)
{
<tr>
<td><span>#task.ClientId</span></td>
<td><span class="nowrap">#task.TaskDescription</span></td>
<td><span class="nowrap">#task.CurrentState</span></td>
<td><span >#task.AssignedBy.Replace("CORPORATE\\", "").Replace(#".", " ")</span></td>
<td><span>#task.AssignedTo.Replace("CORPORATE\\", "").Replace(#".", " ")</span></td>
<td><span>#task.DateOpened.ToString("dd/MM/yyyy HH:mm")</span></td>
<td><span>#task.DateDue.ToString("dd/MM/yyyy HH:mm")</span></td>
#* <td><span>#(task.DateClosed.HasValue ? task.DateClosed.Value.ToShortDateString() : " - ")</span></td>*#
<td>
<span class="nowrap">
#Html.DropDownList(
"Outcomes",
new SelectList(task.Outcomes, "Id", "Name"), "---Please Select ---",
new Dictionary<string, object>
{
{"data-case-id", #task.CaseId }, {"data-task-log-id", #task.TaskLogId}, {"data-client-id", #task.ClientId}
})
</span>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="modal hide span8" id="complete-task-modal" tabindex="-1" role="dialog" aria-labelledby="complete-task-header" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="complete-task-header">Complete Task</h3>
</div>
<div class="modal-body">
<div class="row">
<div class="span8">
<div class="alert alert-info">
<label id="CurrentState"></label>
<label id="NewState"></label>
<label>Generated Tasks</label>
<ul id="task-list">
</ul>
</div>
</div>
</div>
<form id="form">
<input type="hidden" id="task-log-id" name="taskLogId" />
<input type="hidden" id="case-id" name="caseId" />
<input type="hidden" id="outcome-id" name="triggerId" />
<input type="hidden" id="client-id" name="clientId" />
<div id="popup">
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn" id="close" data-dismiss="modal" aria-hidden="true">Go Back</button>
<button class="btn btn-primary" id="confirm-task">Confirm</button>
</div>
</div>
</div>
This is the controller method.
public ActionResult Index(DateTime? from, DateTime? to)
{
var usergroups = GetGroups(HttpContext.User.Identity.Name);
var model = _taskLogger.GetTasks(from, to)
.Select(task => new TaskViewModel
{
TaskLogId = task.TaskLogId,
CaseId = task.CaseId,
ClientId = task.ClientId,
TaskDescription = task.Description,
AssignedBy = task.AssignedBy,
AssignedTo = task.AssignedTo.Trim(),
DateOpened = task.DateCreated,
DateClosed = task.DateClosed,
DateDue = task.DateDue
}).ToList()
.Where(x => IsAvailableToUser(x.AssignedTo, usergroups))
.OrderBy(x => x.DateDue);
foreach (var task in model)
{
var workflow = _workflowEngine.GetCase(task.CaseId);
task.CurrentState = workflow.State.ToNonPascalString();
task.Outcomes = workflow.GetPermittedTriggers().OrderBy(x => x.Name).ToList();
}
ModelState.Clear();
return View(model);
}
When the model is returned following the ajax post, the dataset is different, as expected, however, within the datatable in the view it still displays the old data.
Having done some googling on this issue, I've tried clearing the modelstate but that makes no difference and from what I've read, it only seems to affect HTMLHelpers anyway.
I'm not sure if this is an issue with the datatable or just a refresh issue with the view itself. Any input would be appreciated.
Ajax calls stays on the same page. If you want to update the page with the view returned by public ActionResult Index(DateTime? from, DateTime? to) then you need to add it to the DOM in the success callback
$.ajax({
url: '#Url.Action("Index", "Home")',
data: { from: "10/01/2014", to: "10/14/2014" },
dataType: "html",
success: function (data) {
$('#someElement').html(data); // add the returned html to the DOM
},
....
});
but looking at the code in the controller it appears to be the same view as the original view so perhaps you really want to redirect rather than stay on the same page

User searchs DB for record, if found and viewed, attempt to return shows 'webpage expired'

So in my MVC Orchard application the user chooses a location from a DD & selects a date from a datepicker. Search then looks through the DB table and returns a list of results (if any). User can then use the 'View' button to view each record on screen. This all works fine, however if the user presses the 'back' button, after viewing the record I get the error:
Webpage has expired
I've looked through other examples of GET and POST in my code and I can see no diff. does anyone have any idea why this is happening, think it is something to do with the search, please see code below
#model Project.ViewModels.SearchDeliveryRunsVM
#{
Script.Require("ShapesBase");
Layout.Title = T("Delivery Runs History").ToString();
Script.Require("jQuery");
Script.Require("jQueryUI");
Style.Require("jQueryUI_DatePicker");
}
#using (Html.BeginFormAntiForgeryPost())
{
<div>
<div style="display:inline-block">
<div class="editor-label">Delivery Run</div>
<div class="editor-label">#Html.DropDownList("DeliveryRunId", Model.DeliveryRunList)</div>
</div>
<div style="display:inline-block">
<div class="editor-label">#T("Date")</div>
<div class="editor-label">#Html.TextBoxFor(model => model.SelectedDate, new { #class = "jquery_datepicker", #Value = Model.SelectedDate.HasValue ? Model.SelectedDate.Value.ToString("dd/MM/yyyy") : string.Empty })</div>
</div>
<button style="display:inline-block" type="submit">#T("Search")</button>
</div>
if (Model.Orders != null && Model.Orders.Count() > 0)
{
<br />
<table class="items">
<colgroup>
<col id="Col10" />
<col id="Col11" />
</colgroup>
<tr>
<th>Order Id</th>
<th>Customer</th>
<th>Value</th>
<th>Payment</th>
<th>Signature</th>
<th></th>
</tr>
#foreach (Project.Models.OrderInfo results in Model.Orders)
{
<tr>
<td>#results.OrderRecordId</td>
<td>#results.QbCustName</td>
<td>#results.Value</td>
<td>#results.Payment</td>
<td>#Html.CheckBoxFor(x => results.Signature, new { disabled = "disabled" })</td>
<td>
<div>
#T("ViewOrder")
</div>
</td>
</tr>
}
</table>
}
else
{
if (!Model.IsInitialGet)
{
<p>No records exist</p>
}
}
}
#using (Script.Foot())
{
<script type="text/javascript" language="javascript">
$(function () {
var dates = $("#SelectedDate").datepicker({
dateFormat: 'dd/mm/yy'
}).val("#(Model.SelectedDate.HasValue ? Model.SelectedDate.Value.ToString("dd/MM/yyyy") : DateTime.Now.ToString("dd/MM/yyyy"))");
});
</script>
}
UPDATE
All the other search features on my site are using the Index function of each controller, then in the view using something like:
#using(Html.BeginForm("Index", "CustomerAdmin", FormMethod.Get)) {
<fieldset class="bulk-actions">
<label for="search">#T("Search:")</label>
#Html.TextBoxFor(m => m.SearchExpression)
<button type="submit">#T("Search")</button>
#T("Clear")
</fieldset>
}
to use the GET to display the results, where as my problem I am using GET and POST. perhaps?
It is normal that a page created by a POST action expires after the page is navigated away from; you wouldn't, for example, want the back button to trigger a second credit card charge attempt... You could try using output caching

Redirect to Action-Controller MVC 4 inside Jquery

I need a little help with this since I am very new to AJAX in general. In a given page that I have (a view) I display a button which brings up a form. What I ultimately want is to pass the data input in that form to a controller inside my application. I know there are plenty of tutorials on how to do it out there...however, I seem to have a problem understanding how this is done; therefore, I want to traverse this step-by-step. I just simply want to display a different view after the user clicks on the "Save" button on the dialog. I hope that is clear. Here is my HTML + jQuery
#model AccommodationEditViewModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<table>
<tr>
<td>
#Html.ActionLink("Back to list", "List", "Accommodation")
</td>
</tr>
<tr>
<td>
#if ( Model.Accommodation.LocaleID != Guid.Empty)
{
#Html.DisplayAccommodation(IAccommodationDisplay);
}
</td>
</tr>
</table>
<div class="genericform">
<form id="form" method="post">
#Html.AccommodationEditDisplay()
<table>
<tr>
<td>
#Html.ActionLink("Add New Address", "", "", new { id = "addaddresses" }, null)
</td>
</tr>
#if (Model != null && Model.Accommodation.Addresses.Count() == 0)
{
<tr>
<td>
This Locale Contains No Addresses
</td>
</tr>
}
else
{
foreach (Address address in Model.Accommodation.Addresses)
{
<tr>
<td>
#address.Address1
</td>
</tr>
}
}
</table>
<br /> <br />
<input type="submit" name="command" value="Save" />
<input type="submit" name="command" value="Delete" />
</form>
</div>
<button id="opener">Add Address</button>
<div id="dialog" title="Add Address" style="display:none;">
<label for="Address1">Address: </label><input id="Address1" />
<label for="Address2">Address 2: </label><input id="Address2" />
<label for="City">City: </label><input id="City" />
<label for="State">State: </label><input id="State" />
<label for="PostalCode">Postal Code: </label><input id="PostalCode" />
</div>
<script type="text/javascript" src="~/Scripts/jquery-1.7.1.js"></script>
<script type="text/javascript" src="~/Scripts/jquery-ui-1.8.20.js"></script>
<link type="text/css" href="~/Content/themes/base/jquery.ui.all.css" rel="stylesheet" />
<script type="text/javascript">
$(document).ready(function () {
$("#dialog").dialog({
autoOpen: false,
show: {
effect: "explode",
duration: 250
},
hide: {
effect: "explode",
duration: 250
},
buttons: {
"Save": {
text: "Save",
class: "",
click: function () {
//**redirect here**
$(this).dialog("close");
}},
"Cancel": {
text: "Cancel",
class: "",
click: function () {
$(this).dialog("close");
}
}},
modal: true
});
$("#opener").click(function () {
$("#dialog").dialog("open");
});
});
</script>
I have tried using $.ajax({}) and setting this: Url: "/Areas/Website/Controller/Action
but scripting stops working at that point.
Any and all help is appreciated! Thank you!
EDIT
Do I even need to use AJAX at all? I just want to pass the information in that form (inside the dialog) to a controller.
Ok, try replacing your <form id="form" method="post"> form fields </form> with
#using (Html.BeginForm("NameOfControllerMethod", "NameOfControllerClass"))
{
<!-- fields for gathering data, your input fields essentially -->
}
THEN you need to go to your controller class, and add [HttpPost] above your controller method, like this:
[HttpPost]
public ActionResult MethodName(AccomodationEditViewModel viewModel) {
//do stuff in here with the viewModel, for example viewModel.Location, or viewModel.Name
}
NOTE that the [HttpPost] requires that you add a new "using" insert at the top of your controller class.
The NameOfControllerMethod is the method that has the HttpPost above it. The name of the controller class is like "MyClass", coming from the controller named MyClassController, as an example.
Try this:
window.location = "/Areas/Website/Controller/Action";
inside your click function.

C# MVC4 Jquery Ajax Post Partial View Update

I have the following partial view.
#using System.Data;
#using System.Dynamic;
#using System.Collections.Generic;
#using System.Linq;
#model TheMProject.Models.MyViewModel
<div id="Item_Buttons">
<h2 class="alignleft">Table 1</h2>
<p class="alignright">Item Name<input type="text" name="item_name" value="#Html.ValueFor(x => x.itemname)" class="search-query" placeholder="Search" style ="width:100px"/>
<button class="btn btn-success" id="Change_Item_Name" value="Change_Item_Name" name="action:Change_Item_Name" type="button"> Change Item Name</button>
Grade<input type="text" name="item_grade" value="#Html.ValueFor(x => x.grade)" class="search-query" placeholder="Search" style="width:100px"/>
<button class="btn btn-success" id="ChangeItemGrade" value="ChangeItemGrade" name="action:Change_Grade" type="button">Change Grade</button>
Delete Record<input type="text" name="delete_item" value="#Html.ValueFor(x => x.itemname)" class="search-query" placeholder="Search" style ="width:100px"/>
<button class="btn btn-success" id="DeleteItem" value="DeleteItem" name="action:Delete_Item" type="button">Delete Record</button>
</p>
<div style="clear: both;"></div>
</div>
<section>
<div id ="firstgrid">
<table id="TTable" class="gridTable">
<thead class="gridHead">
<tr>
#Html.DisplayFor(x => x.TColumns)
</tr>
</thead>
<tbody>
#Html.DisplayFor(x => x.TRows)
</tbody>
</table>
</div>
</section>
<section>
<form id="form1">
<div id="grid">
<table id="CTable" class="gridTable">
<thead class="gridHead">
<tr>
#Html.DisplayFor(x => x.Columns)
</tr>
</thead>
<tbody>
#Html.DisplayFor(x => x.Rows)
</tbody>
</table>
</div>
</form>
</section>
<section>
<div id ="Display_Average">
<table id="AvgDisplayTable" class="gridTable">
<thead class="gridHead">
<tr>
#Html.DisplayFor(x => x.AvgColumns)
</tr>
</thead>
<tbody>
#Html.DisplayFor(x => x.AvgRows)
</tbody>
</table>
</div>
</section>
<button class="btn" id="SubmitAverage" value ="SubmitAverage" name="action:SubmitAverage" type="button">Submit Averages</button>
<div id="ItemNameDiv" title="Change Item Name">
#using (Html.BeginForm("ChangeItemName", "Home", "POST"))
{
<section>
Heat Name:<input type="text" name="itemName" value="#Html.ValueFor(x => x.heatname)" style ="width:100px"/>
Change to:<input type="text" name="updatedName" value="" style="width: 100px" />
<input type="button" id="ChangeItemName" name="ChangeItemName" value="Change" />
</section>
}
</div>
<div id="ItemGradeDiv" title="Change Item Grade">
#using (Html.BeginForm("ChangeGrade", "Home", "POST"))
{
<section>
Item Grade:<input type="text" name="grade" value="#Html.ValueFor(x => x.grade)" style ="width:100px"/>
Change to:<input type="text" name="updatedName" value="" style="width: 100px" />
<input type ="hidden" name="hiddenItem" value ="#Html.ValueFor(x => x.itemname)" />
<input type="submit" name="ChangeGrade" value="Change" />
</section>
}
</div>
<div id="DeleteItemDiv" title="Delete Item">
#using (Html.BeginForm("DeleteItem", "Home", "POST"))
{
<section>
Heat Name:<input type="text" name="itemName" value="#Html.ValueFor(x => x.itemname)" style ="width:100px"/>
<input type="submit" name="DeleteItem" value="Delete" />
</section>
}
</div>
When the Change Item Name button is clicked, an ajax post is called with jquery as seen here:
$(document).ready(function () {
$('#ChangeItemName').click(function (e) {
var tdata = $('#form1').serialize();
var origname = $('#ItemNameDiv').find('input[name="itemName"]').first().val();
var newname = $('#ItemNameDiv').find('input[name="updatedName"]').first().val();
$.ajax({
type: "POST",
data: {
mCollection: tdata,
itemName: origname,
updatedName: newname
},
url: "Home/ChangeItemName",
success: function (result) { success(result); }
});
});
function success(result) {
$('#ItemNameDiv').dialog('close');
$("#My_Partial_V").html(result);
}
});
. Upon completion, the partial view is refreshed with the updated data from the post. Including the jquery required for this post, there are other scripts required to perform other actions in the view such as hiding the divs shown below the submit average button until other buttons are clicked. After the first time the previously mentioned ajax post is performed, if the same button is clicked the post is called twice instead of once, the third time its clicked it runs 4 times, etc.
Ive tried moving the script reference
<script src="#Url.Content("~/Scripts/partialitemscripts.js")"
type="text/javascript"></script>
outside of the partial view and into the view which contains the partial as well as into the layout file. When I try these two methods everything loads correctly until the partial view is refreshed at which time all the scripts fail to be called/referenced.
You could try to move the script outside of the Partialview and into the mainview (like you said), but change it a little: instead of triggering the function when the document is loaded, put it all in a function:
function ajaxCallback(result){
$('#ChangeItemName').click(function (e) {
var tdata = $('#form1').serialize();
var origname = $('#ItemNameDiv').find('input[name="itemName"]').first().val();
var newname = $('#ItemNameDiv').find('input[name="updatedName"]').first().val();
$.ajax({
type: "POST",
data: {
mCollection: tdata,
itemName: origname,
updatedName: newname
},
url: "Home/ChangeItemName",
success: function (result) { success(result); }
});
});
}
Then you call this function from the ready event of your main view (the one that contains the partial).
To fix your button not working anymore when you've done an ajax request you've got to update your success-function to call the ajaxCallback (this would be in the partialitemscripts.js together with the ajaxCallback function):
function success(result) {
$('#ItemNameDiv').dialog('close');
$("#My_Partial_V").html(result);
ajaxCallback();
}
I'm not sure it this is the ideal solution, but I managed to get something similar working this way.
Although it is hard from the code posted to make sure. It seems that the reason the scripts fail after the first time is because you use the .html() which adds elements to the DOM and the click() event has not been binded to those new elements.
In this case you should use on() or delegate(). See the jquery documentation for how to use those. It is simple.

Categories