Add row information into Ajax.BeginForm Confirm message - ajax

I have a table with several columns. The first column contains a location name and the last column contains a delete button. When I click any of the delete buttons, it currently displays the confirmation message "Are you sure you want to delete the location:" I want the end of the confirmation message to display the location name.
Here are the relevant bits in my view:
#using (Ajax.BeginForm("FirstAjax", "Configuration", null, new AjaxOptions()
{
Confirm = "Are you sure you want to delete the location:\n",
HttpMethod = "POST",
OnFailure = "deleteFailed",
UpdateTargetId = "CustomLocations"
},
new { #id = "deleteLocation" }
))
{
<div id="reportTblDiv">
<table id="CustomLocations">
<tbody>
#foreach (var location in Model.LocationList)
{
<tr>
<td class="location">#location.LocationName</td>
<td>
<input type="submit" title=#Model.DeleteButton name="#location.LocationId" value="#Model.DeleteButton" />
</td>
</tr>
}
</tbody>
</table>
</div>
}
How can I access the correct element in Model.LocationList from the line beginning with Confirm?

Set the id of the first to be the same as the name as the second . Add a handle to the submit in javascript to update the confirm message:
<td id=#location.LocationId class="location">#location.LocationName</td>
<td>
<input type="submit" title=#Model.DeleteButton name="#location.LocationId" value="#Model.DeleteButton" onclick="return btnDeleteClicked(this);"/>
</td>
<script>
function btnDeleteClicked(btnObject){
var tLocation=$(btnObject).attr('name');
var tCurrentMessage=$("#deleteLocation").data('ajax-confirm');
$("#deleteLocation").data('ajax-confirm',tCurrentMessage + tLocation);
return true;
}
</script>

Related

When using AjaxHelper to retrieve a partial view, the embedded data is always the same

We use ASP.NET MVC 5's AjaxHelper and Ajax.BeginForm to request a partial view. That request also needs some JSON data in order to update a map control.
The view rendering part of the process works great (a table body is replaced with the strongly-typed partial view), but the JSON data (embedded into the data-json attribute of the div element as described in this answer and retrieved in my OnSuccess function) always has the same value.
To eliminate the controller code or ViewBag as culprit, I replaced the JSON data (originally retrieved from the ViewBag) with a direct call to DateTime.Now. Sure enough, the same DateTime is printed each time in updateMap() (e.g., 2/11/2016+5:24:42+PM)
I've tried disabling caching, and changing the HTML method to Post, in my AjaxOptions.
In the Parent View (changing the ListBox selection submits the form):
#model string
#{
ViewBag.Title = "Project List";
AjaxOptions ajaxOpts = new AjaxOptions
{
UpdateTargetId = "tableBody",
OnSuccess = "updateMap",
HttpMethod = "Post",
AllowCache = false
};
}
#using (Ajax.BeginForm("GetProjectsData", ajaxOpts))
{
<fieldset>
<legend>Project State</legend>
<div class="editor-field">
#Html.ListBox("selectedStates", ViewBag.StatesList as MultiSelectList,
new { #class = "chzn-select", data_placeholder = "Choose States...", style = "width:350px;", onchange = "$(this.form).submit();" })
</div>
</fieldset>
}
<table class="table">
<thead>
<tr>
<th>
Project Name
</th>
<th>
Project Firm
</th>
<th>
Project Location
</th>
<th>
Building Type
</th>
<th>
Project Budget
</th>
<th></th>
</tr>
</thead>
<tbody id="tableBody">
#Html.Action("GetProjectsData", new { selectedStates = Model })
</tbody>
</table>
<script>
function updateMap() {
var jsonData = $("#geoJsonData").attr("data-json");
var decoded = decodeURIComponent(jsonData);
console.log(decoded); // always prints same value
}
</script>
The partial view:
#model IEnumerable<OurModel>
<div id="geoJsonData" data-json="#Url.Encode(DateTime.Now.ToString())"></div>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.NAME)
</td>
<td>
#Html.DisplayFor(modelItem => item.COMPANY_NAME)
</td>
<td>
#Html.DisplayFor(modelItem => item.STATE)
</td>
<td>
#Html.DisplayFor(modelItem => item.BUILDING_TYPE)
</td>
<td>
#Html.DisplayFor(modelItem => item.BUDGET_AMT)
</td>
</tr>
}
I'm hesitant to jettison the MVC helper classes' pattern of returning a partial view and instead manually render a view into a JSON object. Why is the updated tablebody visible on screen, but when jQuery requests the div element it always has the same data?
Interesting...replacing the div with a good old hidden input element worked. Now fresh data is retrieved each time.
This
<div id="geoJsonData" data-json="#Url.Encode(DateTime.Now.ToString())"></div>
Became this
<input id="geoJsonData" type="hidden" value="#Url.Encode(DateTime.Now.ToString())" />
I wonder why the data-json in the div remained "stale" while the value of the input field did the trick?

Get first and second td element in row

I have an ajax call attached to the click event of a pic inside a table row. Once the pic is clicked and the click event initiated, I need to grab the first and second td elements from that row. I'm new to jQuery so what I have below is my latest attempt (not working..). The variables firstName and lastName both wind up being undefined after those lines are executed
$('.checkErrors').click(function () {
var firstName = $(this).parent('tr td:first-child').val();
var lastName = $(this).parent('tr td:nth-child(2)').val();
$.ajax({
type: 'GET',
url: '#Url.Action("GetErrors","AgentTransmission")',
data: { term: $(this).attr('id') },
.
.
});
});
Here is a sample table row. The image in the last td element contains the .click event. I would like to grab the first two that contain the text "phinneas" and "ferbseven".
<tr>
<td>
phinneas
</td>
<td>
ferbseven
</td>
<td nowrap>
7735
</td>
<td>
Agent
</td>
<td>
SAF
&nbsp
07070900
</td>
<td>
6/5/2013 10:35:38 AM
</td>
<td>
DANTAK
</td>
<td class="errorPlus">
Error
</td>
<td>
Details
<span> | </span>
Edit
</td>
<td align=center id=2358>
<img src="/Content/images/magnify.gif" class="checkErrors" id=2358 alt="Program Details" />
</td>
</tr>
use closest
var $tr = $(this).closest(´tr´);
var firstName = $tr.find('td:first-child').text();
var lastName = $tr.find('td:nth-child(2)').text();
Also, you need to use text instead of val for td elements since it make sense only on input controls.
First only form elements have .val property so .
You are supposed to use .text since it is a td
Try using :eq psuedo selector
var $tr;
$tr.find('td:eq(0)').text();
$tr.find('td:eq(1)').text();
To get their content, you can do this:
var cells = $(this).closest('td').siblings('td');
var firstName = cells.eq(0).text();
var firstName = cells.eq(1).text();
Those last two lines can also be:
var firstName = $(cells[0]).text();
var firstName = $(cells[1]).text();

jQuery .append(html) command appending incorrectly

I am using a jQuery/Ajax call to append a partial view to a table. When the page loads, the partial view is created correctly. However, once the use attempts to append another item to the table, the formatting is incorrect despite the exact same partial view being used.
Here is the table. When this loads, the items are loaded onto the page correctly as the picture below illustrates:
<table id="fixedRows">
<thead>
<tr>
<th>State Code</th>
<th>Agent ID</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.BankListAgentId)
{
if (!String.IsNullOrWhiteSpace(item.AgentId) && item.FixedOrVariable.Equals("F"))
{
#Html.EditorFor(model => item, "FixedPartialView")
}
}
</tbody>
</table>
<br />
Add Another
Once you click the Add another link, this jQuery/Ajax call is activiated
<script type="text/javascript">
$(document).ready(function () {
$(".addFixed").click(function () {
//alert('test');
event.preventDefault();
$.ajax({
url: '#Url.Action("BlankFixedRow", "BankListMaster")',
cache: false,
success: function (html) { $("#fixedRows").append(html); }
});
});
$("#addVariable").click(function () {
event.preventDefault();
$.ajax({
url: '#Url.Action("BlankFixedRow", "BankListMaster")',
cache: false,
success: function (html) { $("#variableRows").append(html); }
});
});
});
</script>
That jQuery calls this method from the controller
public ViewResult BlankFixedRow()
{
SelectList tmpList = new SelectList(new[] { "AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NA", "NM", "NY", "NC", "ND", "MP", "OH", "OK", "OR", "PW", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "US", "VT", "VI", "VA", "WA", "WV", "WI", "WY" });
ViewBag.StateCodeList = tmpList;
return View("FixedPartialView", new BankListAgentId());
}
Which calls this partial view
EDIT(a couple people noticed the id tag missing from the <tr>, this was just a copy/paste error for this post, the actual code has the id tag)
#model Monet.Models.BankListAgentId
#{
Layout = null;
}
#using (Html.BeginCollectionItem("BankListAgentId"))
{
<tr id="item-#Model.AgentId">
<td>
#Html.DropDownListFor(model => model.StateCode,
(SelectList)ViewBag.StateCodeList, Model.StateCode)
</td>
<td>
#Html.EditorFor(model => model.AgentId)
#Html.ValidationMessageFor(model => model.AgentId)
</td>
<td>
delete
</td>
#*<td>Delete</td>*#
</tr>
}
This is the same partial view that is called when the page first loads, which part of why I'm confused that the end result after hitting the Add another link turns out looking like this
EDIT
If you hit the Add another link twice, this is the result
EDIT
I've tried the following jQuery sucess commands with no luck
success: function (html) { $("#fixedRows > tbody:last").append(html); }
success: function (html) { $("#fixedRows tr:last").after(html); }
success: function (html) { $("#fixedRows > tbody").append(html); }
Here is the HTML that is rendered after the Add another link is clicked. I included the opening <form> tag for the form below it to show that the new rows are nowhere to be found.
<form action="/BankListMaster/Edit/11" method="post">
<fieldset>
<legend>Stat(s) Fixed</legend>
<table id="fixedRows">
<tr>
<th>State Code</th>
<th>Agent ID</th>
<th></th>
<th></th>
</tr>
<tr id="item-1164998320">
<td>
<select id="item_StateCode" name="item.StateCode"><option value="">HI</option>
<option>AL</option>
..
<option>WY</option>
</select>
</td>
<td>
<input class="text-box single-line" id="item_AgentId" name="item.AgentId" type="text" value="1164998320" />
<span class="field-validation-valid" data-valmsg-for="item.AgentId" data-valmsg-replace="true"></span>
</td>
<td>
delete
</td>
</tr>
<tr id="item-1164998219">
<td>
<select id="item_StateCode" name="item.StateCode">
<option value="">HI</option>
<option>AL</option>
..
<option>WY</option>
</select>
</td>
<td>
<input class="text-box single-line" id="item_AgentId" name="item.AgentId" type="text" value="1164998219" />
<span class="field-validation-valid" data-valmsg-for="item.AgentId" data-valmsg-replace="true"></span>
</td>
<td>
delete
</td>
</tr>
<tr id="item-0352926603">
<td>
<select id="item_StateCode" name="item.StateCode">
<option value="">GA</option>
<option>AL</option>
..
<option>WY</option>
</select>
</td>
<td>
<input class="text-box single-line" id="item_AgentId" name="item.AgentId" type="text" value="0352926603" />
<span class="field-validation-valid" data-valmsg-for="item.AgentId" data-valmsg-replace="true"></span>
</td>
<td>
delete
</td>
</tr>
</table>
<br />
Add Another
</fieldset>
</form>
Add Another
<form action="/BankListMaster/Edit/11" method="post">
EDIT
Here is a screen shot of the table in Chrome's debugger after the Add Another link is clicked. As you can see, the data pulled from the table is loaded properly in respective <tr> tags, however the empty row (which is sent via the same partial view as the rest) doesn't have any of the same table elements. The screen shot below that shows Response, however, which does include the <tr> tags
EDIT
I put a console.log(html) line in the success Ajax function so it now reads
success: function (html) {
console.log(html);
$("#fixedRows > tbody").append(html);
}
Here is the console output (state edited for readability)
<input type="hidden" name="BankListAgentId.index" autocomplete="off" value="3f7e0a92-8f20-4350-a188-0725919f9558" />
<tr>
<td>
<select id="BankListAgentId_3f7e0a92-8f20-4350-a188-0725919f9558__StateCode" name="BankListAgentId[3f7e0a92-8f20-4350-a188-0725919f9558].StateCode">
<option>AL</option>
..
<option>WY</option>
</select>
</td>
<td>
<input class="text-box single-line" id="BankListAgentId_3f7e0a92-8f20-4350-a188-0725919f9558__AgentId" name="BankListAgentId[3f7e0a92-8f20-4350-a188-0725919f9558].AgentId" type="text" value="" />
</td>
<td>
delete
</td>
</tr>
What a complete nightmare...
First off, the HTML that was being returned as viewable in Chrome's debugger was fine, however when I clicked on "View Source" for the page, I could not see anything but what was originally loaded. After finding this post, I found that this is normal. I then used this Chrome add-on to finally see that the <tr> and <td> tags were being stripped out. By simply adding an opening and closing tag to the append statement, I got the returned items to append to the table.
$(".addFixed").click(function () {
$.ajax({
url: '#Url.Action("BlankFixedRow", "BankListMaster")',
dataType: 'html',
cache: false,
success: function (html) {
$("#fixedRows > tbody").append('<tr>' + html + '</tr>');
}
});
});
I see a few things here. You're referencing <tbody> in some of your code but I don't see it anywhere in the page. So first I would suggest using <thead> and <tbody>. In your partial view I see <tr "item-#Model.AgentId"> which should have an id.
You should also remove the onclick handler and the delete button and put that in with the rest of your JavaScript. Set a class on your delete links instead.
For links that don't need urls and are only used for attaching JavaScript handlers, I recommend using href="javascript:void(0)" as this would prevent the browser from doing anything special with href="#" so then you'll be able to remove the calls to preventDefault().
As to the source of your problem, $("#fixedRows tbody").append(html) is the code you want so no need to try after(). It looks like your html is getting stripped. Try setting the dataType attribute in the $.ajax() call to html.

Using a partial view to represent a table row

I am trying to use a partial view to represent rows of a table in my project. I currently have
<table>
<thead>
<tr>
<th >
Column 1
</th>
<th >
Column 2
</th>
<th >
Column 3
</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model.Items)
{
#Html.Action("ItemCalculatedView", new { Id = item.Id})
}
</tbody>
</table>
In my partial view I have this
#using (Ajax.BeginForm("SaveStuff", "Whatever",
new { id = #Model.Id }, new AjaxOptions()
{
HttpMethod = "Post",
OnSuccess = "Success"
}))
{
#Html.HiddenFor(m => m.Id)
<tr>
<td>
#Html.Label("Col1", Model.Col1)
</td>
<td>
#Html.TextBox("Number", Model.Number)
</td>
<td>
<input type="submit" id='submit-#Model.Id'/>
</td>
</tr>
}
How can I make this work?
You can put a form inside a table cell, but you can't have the form inside a tbody element, or spanning multiple columns. So there are three options:
Use a CSS layout instead of a table, or use divs with CSS display set to "table". (for example)
Put the entire form (TextBox and Submit) inside a td
Put another table inside the td element
I'd recommend #1 -- use a CSS layout to construct the table, since it's difficult to style table tags:
Main
<div class="table">
<div class="header-row">
<div class="header-cell">Column 1</th>
<div class="header-cell">Column 2</th>
<div class="header-cell">Column 3</th>
</div>
#foreach(var item in Model.Items)
{
#Html.Action("ItemCalculatedView", new { Id = item.Id})
}
</div>
Partial
#using (Ajax.BeginForm(
actionName: "SaveStuff",
controllerName: "Whatever",
routeValues: new { id = #Model.Id },
ajaxOptions: new AjaxOptions
{
HttpMethod = "Post",
OnSuccess = "Success"
},
htmlAttributes: new { #class = "row" }
))
{
<div class="cell">
#Html.HiddenFor(m => m.Id)
</div>
<div class="cell">
#Html.Label("Col1", Model.Col1)
</div>
<div class="cell">
#Html.TextBox("Number", Model.Number)
</div>
<div class="cell">
<input type="submit" id='submit-#Model.Id'/>
</div>
}
CSS
.table { display: table; }
.header-row, row { display: table-row; }
.header-cell, cell { display: table-cell; }
You have several issues here. First, as dbaseman mentions, you can't place forms within the structure of a table and have it be legal HTML. It may work, or it might not, and even if it does work, you can't guarantee it will continue to work.
I would instead wrap your table in the form, and then on the post figure out which button was pressed based on its value and/or index.
I would strongly advise against using css tables for tabular data. It's just not semantically correct.
Another possible solution is, instead of using the Ajax.BeginForm, instead use jQuery $.ajax and then you can select a row of data in javascript to post to the server.

How to retrieve multiple records from Jquery to my RazorView page

I have a button "btnGetAddress" on my razor page .On clik of this button,I am calling a Jquery to get my addressItmes object to be displayed on to my View page.
On clicking "btnGetAddress" I am able to hit my "JsonResult GetAddresses()" and retrieve records within my Jquery (success: function (data)).and this data has multiple address records. But I do not know how to take this data to my view .Please help me to get my data to be displayed on to my View
When my page get loaded,the user will see only the "btnGetAddress" button .When the user click on the btnGetAddress, it will call the Jquery Click function to fetch all address records from database and display each set of records on the page
$("#btnGetAddress").click(function () {
debugger;
var selected = $("#ddlType").val();
if (selected == "")
{ selected = 0; }
var dataToSend = {
SelectedTypeId: selected
};
$.ajax({
type: "GET",
url: '#Url.Action("GetAddresses", "Content")',
data: { SelectedTypeId: selected },
success: function (data) {
debugger;
},
error: function (error) {
var verr = error;
alert(verr);
}
});
pasted below is my JsonResult GetAddresses() which gets called to retrieve addressItems
public JsonResult GetAddresses()
{
model.AddressItems = AddressService.RetrieveAllAddress();
// My AddressItems is of type IEnumerable<AddressItems>
return Json(model.AddressItems, JsonRequestBehavior.AllowGet);
}
Here is my razor View Page where the address records are to be displayed.
........................
<input type="submit" id="btnGetAddress" name="btnSubmit" value="Show Addresses" />
if (!UtilityHelper.IsNullOrEmpty(Model.AddressItems))
{
foreach (var AddressRecord in Model.AddressItems)
{
<fieldset >
<legend style="padding-top: 10px; font-size: small;">Address Queue(#Model.NumRecords)
</legend>
<table>
<tr>
<td>
<span>Index</span>
</td>
<td>
</td>
<td>
<input type="submit" id="btnDelete" name="btnSubmit" value="X" />
<br />
</td>
</tr>
<tr>
<td>
<span>Address1</span>
<br />
</td>
<td>
#Html.EditorFor(model => AddressRecord.Address )
#Html.ValidationMessageFor(model => AddressRecord.Address)
</td>
</tr>
<tr>
<td>
<span>Description</span>
<br />
</td>
<td>
#Html.EditorFor(model => AddressRecord.Description)
#Html.ValidationMessageFor(model => AddressRecord.Description)
</td>
</tr>
<tr>
<td>
<input type="submit" id="btnSave" name="btnSubmit" value="Save" />
</td>
<td>
<input type="submit" id="btnDelete" name="btnSubmit" value="Delete" />
</td>
</tr>
</table>
</fieldset>
}
}
<fieldset>
Or is there any better way to achieve my objective?
Since you are getting the data via ajax you should use a jquery template engine. Basically get the data the way you are and on success you do something like
<script language="javascript" type="text/javascript">
$(function () {
$.getJSON("/getprojects", "", function (data) {
$("#projectsTemplate").tmpl(data).appendTo("#projectsList");
});
});
</script>
<script id="projectsTemplate" type="text/html">
<section>
<header><h2>Projects</h2></header>
<table id="projects">
<th>Name</th>
{{tmpl(items) "#projectRowTemplate"}}
</table>
</section>
</script>
<script id="projectRowTemplate" type="x-jquery-tmpl">
<tr>
<td>${name}</td>
</tr>
</script>
<div id="projectsList"></div>
Now each template engine is different but the above gives you an idea of what you can do
If you want to return JSON object in your controller, you are going have to turn your view into a string and return it as part of the message. If you google there are some methods out there that can do this.
However, I really think that's the hard way, why not take the data you get from the JSON in the controller and put it in a MODEL and then return your VIEW with the model data passed in. I think that's the easier way.

Resources