Find the control of dynamically added partial view span content in JQuery - c#

We have partial view View1 as follows:
#using (Html.BeginCollectionItem)
{
<div id = "partialview-content>
<table >
<tr>
<td>
#Html.TextBoxFor(x=>x.Name, new {id = "name", #class = "name-class"})
// Additional controls
</td>
</tr>
<tr class="rowSpace">
<td>Label Text</td>
<td>
<span id="business-key-id">
#Html.DisplayFor(x=>x.BusinessKey)
</span>
</td>
</tr>
</table>
}
</div>
When user clicks on Add New Item in Main View, partial view will be added dynamically.
When user enters some text in name textbox in the dynamically added partial view, BusinessKey DisplayFor should be updated dynamically.
So I added below code in the JQuery:
$(document).ready(function () {
$(".name-class").live('keyup', function (event) {
var name1 = $("#name1").val();
var name2 = $("#name2").val();
var name = $(this).val();
(".business-key-id").html(trustName + ' ' + seriesName + ' ' + trancheName);
});
});
Doing this code is updating the business-key-id of all the dynamically added partial views. How can I get the control of the business-key specific to the keydown event control?

This line is selecting all elements with the class name business-key-id
$(".business-key-id").html(...
Change the selector to select only the next element
$(".name-class").on(...
$(this).next('.business-key-id').html(...
Note .live has been depreciated - you should use .on
Edit
Based on OP's revised html, the selector to choose the coresponding business-key-id should be
$(this).closest('table').find('.business-key-id).html(...
And change the html to use the class attribute, not id attribute (duplicate ID's are invalid html)
<span class="business-key-id">
#Html.DisplayFor(x=>x.BusinessKey)
</span>

Related

Put a line of string in textarea everytime I click a checkbox

Basically I want my code to update the textarea as users put a check in a checkboxes inside a table. If a checkbox is checked, a username will be placed in textarea along with line breaks. If unchecked, it will remove from textarea. After that, a button will submit every string inside the textarea.
#using (Html.BeginForm())
{
#Html.AntiForgeryToken();
<td align="center">
<form>
<div style="max-width:50%" class="form-group #if (ViewBag.ErrorMessageDelete != null)
{ <text>has-error</text> } ">
#Html.TextArea("deleteRequest", string.Empty, 5, 100, null)
#if (ViewBag.ErrorMessageDelete != null)
{
<span class="help-block">#ViewBag.ErrorMessageDelete</span>
}
</div>
<button class="btn btn-primary" onclick="return confirm ('Removing these members, are you sure?')">Remove User(s)</button>
</form>
</td>
}
and this is my current checkbox
<td align="center" style="width:5%">
#Html.CheckBox("toBeDeleted", new { onclick = "deleteRequest = deleteRequest + item.username + <br>" });
</td>
I used textarea because I want users to be able to input usernames on their own without using checkboxes. Is it possible to do it in MVC ASP.NET in Visual Studio?
Don't do this with click event. Use change event on checkbox.
You can also try with the array. If the checkbox is checked add item to array, if not remove it. After that convert array to string, and set a value to textarea. Delete and push logic you have to implement by your own.
<td align="center" style="width:5%">
#Html.CheckBox("toBeDeleted", new { onchange="testfunc(this)", data_username = item.username });
</td>
<script>
var result = [];
function testfunc(elem) {
var username = $(elem).attr("data-username");
if($(elem).is(':checked')) {
result.push(username )
}
else{
var index = result.indexOf(username);
if (index > -1) {
result.splice(index, 1);
}
}
$("#deleteRequest").val(result.join("\n"));
}
</script>

ASP MVC - Editor Templates issue (Sends always data from only first template)

I have a form/view which represents a strongly typed model which contains simple properties and an IEnumerable property. I use an editor template for the IEnumerable property of my model.
for (int i = 0; i < #Model.Items.Count(); i++)
{
#Html.EditorFor(model => #Model.Items[i])
}
Now, the template looks like the following:
#using (Html.BeginCollectionItem("Items"))
{
<table style="width: 100%">
<tr>
<td>
#Html.TextBoxFor(model => #Model.ID, new {id = "ID" })
</td>
<td>
#Html.TextBoxFor(model => #Model.Description, readonly="readonly", new {id = "Description" })
</td>
<tr />
<a role="button" id=getDescBtn>
</a>
</table>
}
And my template's script:
<script type="text/javascript">
$(document).ready(function() {
$("#getDescBtn").on('click', function (event) {
$.ajax({
url: '#Url.Action("LoadDescription")',
async: false,
cache: false,
data: {id: $("#ID").val()}
}).success(function (partialView) {
});
});
});
Now, My controller action looks like:
public ActionResult LoadDescription(string id)
{}
Now, Suppose I have two templates:
In the first one, the ID textbox contains the value of "1".
In the second one, the ID textbox contains the value of "2".
When I press the button in the first template, I get to the controller action twice, both with the value of "1" (from the first template).
When I press the button in the second template, I get to the controller action once, with the value of "1" (from the first template, although I pressed the button of the second template).
Now, what I'm trying to achieve is quite simple logically: press button in first template, get to controller action once with value of "1".
press button in secondtemplate, get to controller action once with value of "2".
Also, the action in controller is responsible to calculate value for description and then fill in the description field. What should the action method return (I don't think I should perform a post for the whole form), and how do I receive it within the success function while using Ajax?
Thanks for any help.
I think you need to use classes for your buttons and editors instead of ids. In your code you have multiple text boxes all with Id=ID and multiple buttons with id=getDescBtn. So $("#ID").val() will just give you the value of the first element with id="ID" which is your first textbox.
As for updating the description, you can have your action return the description value and then set the description text box on the success of your ajax call.
#using (Html.BeginCollectionItem("Items"))
{
<table style="width: 100%">
<tr>
<td>
#Html.TextBoxFor(model => #Model.ID, new {#class = "ID" })
</td>
<td>
#Html.TextBoxFor(model => #Model.Description, readonly="readonly", new {#class = "Description" })
</td>
<tr />
<a role="button" class="getDescBtn">
</a>
</table>
}
<script type="text/javascript">
$(document).ready(function() {
$(".getDescBtn").on('click', function (event) {
$.ajax({
url: '#Url.Action("LoadDescription")',
async: false,
cache: false,
data: {id: $(this).parent().find(".ID").val()}
})
.success(function (data) {
$(this).parent().find(".Description").val(data.description )
});
});
});
public JsonResult LoadDescription(string id)
{
//your logic here
return Json(new {description )});
}

MVC 4 : FormCollection Doesn't return radio button

I'm dynamically creating controls in Razor-View. Here I add some controls to my DOM depending on what data is in my object. But when I try to add a radiobutton I don't get it unless the value is constant. If I dynamically add two radio buttons with different values, FormCollection doesn't include those controls.
Please help me with this, as I fail to understand this behaviour. Ideally it should have just returned two radio buttons in collection.
foreach (var property in propertiesInner)
{
if (property.Name == "OptionQuestion")
{
if (#item.ObjQuestions.QuestionType == 4)
{
<td>
<table>
<tr>
<td>
#Html.RadioButton("RadTF", UniqueValue
, false, new { id = "RadTF", #style = "width:auto;background:none;border:none" })
#property.GetValue(itemInner, null)
</td>
</tr>
</table>
</td>
}
else if (#item.ObjQuestions.QuestionType == 1)
{
<td>
<table>
<tr>
<td>
#Html.CheckBox("Chk"+#item.QuestionCode.ToString()+UniqueValue
, false, new { id = "Chk"+#item.QuestionCode.ToString()+UniqueValue
, #style = "width:auto;background:none;border:none" })
#property.GetValue(itemInner, null)
</td>
</tr>
</table>
</td>
}
}
}
EDIT 1:
UniqueValue is my forloop variable. So as to give each button a unique value.Also I tried concatenating this unique variable to my id like this:
#Html.RadioButton("RadTF"+UniqueValue, UniqueValue
, false, new { id = "RadTF"+UniqueValue
, #style = "width:auto;background:none;border:none" })
Value is constant means, if I generate radio buttons with same value I see them(or rather one of them) in the collection on post.
For your radio button group, you must ensure that each radio button:
has a unique id
has the same name
The name attribute is what groups different radio buttons together. You are using this overload:
public IHtmlString RadioButton(
string name,
Object value,
bool isChecked,
Object htmlAttributes
)
Can you try this to create your radio buttons:
#Html.RadioButton("RadTF", UniqueProperty, false, new { id = "RadTF"+UniqueValue, style = "width:auto;background:none;border:none" })
If you still have issues, please post the markup of the rendered form.

MVC 3 Partial View within dialog not working

I have a datatable webpage that shows a list of user in a datatable. On the user page there is a button create new user. On clicking this launches a modal jQuery dialog box for the user to enter details off the new user. There is a Cancel button which just closes the dialog box and a Save User button which on clicking calls DoSaveUser method in my controller. I can see from debugging that I get into the DoSaveUser method which should at the end return to a PartialView if the create user was successful saying User was saved. However my dialog were you enter details is not getting replaced with the Success message - even though the user is getting created - i.e - after I hit the save button - if I then cancel the dialog and refresh the original user page I can see the datatable updated with my new user.
Code on UserList page (there are more fields in the dialog than just forename but have removed them to make question have less code). So when CreateUser button is clicked my newUserDialog is launched.
<div id="newUserDialog">
#using (Html.BeginForm("DoSaveUser", "MyController", FormMethod.Post, new { id = "saveForm" }))
{
<div id="resultContainer">
<table class="ui-widget-content" style="width: 565px; margin-top: 10px;">
<tr>
<td style="width: 100px;">
</td>
<td class="label">
Forename :
</td>
<td class="value">
#Html.TextBoxFor(model => model.Forename, new { style = "width:150px" })
</td>
</tr>
</table>
<div class="ui-widget-content Rounded" style="width: 565px; margin-top: 10px; text-align: center;">
<input id="Cancel" type="button" class="dialog-button" value="Cancel" style="margin: 5px" />
<input id="DoSaveUser" type="submit" class="dialog-button" value="Save User" style="margin: 5px" />
</div>
</div>
}
Javascript code for Save User on the dialog being clicked - submit the form.
$(function () {
$('#saveForm').submit(function () {
var formData = $("#saveForm").serializeArray();
$.ajax({
url: this.action,
type: this.method,
data: formData,
dataType: "json",
success: function (result) {
$('#resultContainer').html(result);
}
});
return false;
});
});
Now in My DoSaveUser method in my controller which I can set a breakpoint and hit and see all the values being sent in correctly for the corresponding fields - once I have saved to the DB this is return.
return PartialView("UserSuccess", model);
And this is all that view contains in the cshtml..note what I wanted was the result container Div which contains all my textbox fields and labels to be replaced with User Created successfully. And then I will need an ok on this page which on clicking will close the dialog box and refresh the UserList page and show the datatable updated with the new user. However when I click save the textboxes just stay on the Div and the Div does not get changed - but if I then cancel the dialog and refresh the page I can see the datatable updated with my new user. Is there something I am missing? (note - i have added jquery.unobtrusive-ajax.js to my _Layout page)
#model MyProject.Models.UserModel
#{
ViewBag.Title = "UserSuccess";
}
<div id="resultContainer">
User Created Successfully
</div>
Are you sure that your initial html do have a #resultContainer div? If you don't the
$('#resultContainer').html(result);
line won't match anything. If you do on the other hand, you will get duplicate nested #resultContainer divs which is also an error (id must be unique).
The right way to do it is to add an empty div in your original html:
<div id="resultContainer"></div>
And in your view output just the content to go inside the div.
#model MyProject.Models.UserModel
#{
ViewBag.Title = "UserSuccess";
}
User Created Successfully
I have to say what you are doing is not a good way of using dialog and partial view in ASP.NET MVC applications. I can give you some simple code to show an idea:
If list.cshtml is a list of users page, and edit.cshtml is a partial view that has an edit form in.
On list page:
$(".grid-row .edit").click(function(){
editUser($(this).attr("data-id"));
});
function editUser(id){
var $dialog=$("#dialogEditUser");
if($dialog.length == 0){
$dialog=$("<div id='dialogEditUser'>").appendTo("body");
}
$dialog.dialog({
...
open:function(){
$dialog.load("/user/edit/"+id, function(){
//todo: handle form events
});
}
});
$dialog.dialog("open");
}
You can also make the open dialog function in a static method, like:
MvcSolution.Dialog = function (id, title, options) {
var $dialog = $("#" + id);
if ($dialog.length == 0) {
$dialog = $("<div id='" + id + "' class='dialog' title='" + title + "'></div>").appendTo("body");
}
$dialog.dialog(options);
$dialog.dialog("open");
};
You can find a good c# and js framework for MVC here

Using jQuery to post back to Controller

In my web page, I have a series of tables that basically just contain rows of information. Each of these is given an id in a for loop and I'm trying to reference them from outside that. I added classes to both the table and a 'Save Changes' button.
Essentially, my goal is for the user to be able to drag and drop rows around, thereby changing the order. Then they can click the 'Save Changes' button and this will post back to the server with the relevant information.
I am having trouble matching up the button to the relevant table and thereby submitting the id's of each row back to the server in an array. I have written the code to be able to be able to get the ids from each of the tables and their current order, but I don't know how to assign this to an array from within the button click jQuery.
Here is the View:
#foreach (var collection in Model.Collections)
{
<h2>#collection.Season</h2>
#Html.ActionLink("Delete Collection", "DeleteCollection", new { controller = "Edit", brand = collection.Brand.Name, season = collection.Season })
#Html.ActionLink("Edit Collection", "EditCollection", new { controller = "Edit", brand = collection.Brand.Name, season = collection.Season })
#Html.ActionLink("Add Image", "CreateImages", new { controller = "Edit", season = collection.Season })
<p>
To change the ordering of images, drag and drop to your desired position and then click the Save Changes button on the appropriate collection.
</p>
<table class="table-collection" id="table-#collection.Id">
<tr class="nodrop nodrag">
<th>
Id
</th>
<th>
Description
</th>
<th>
Image
</th>
<th>
Options
</th>
</tr>
#foreach (var image in collection.Images)
{
<tr id="#collection.Id-#image.Id">
<td class="dragHandle showDragHandle">
#image.Id
</td>
<td>
#image.Description
</td>
<td>
<img src="#Url.Content("~/" + image.Location)" alt="#image.Description" />
</td>
<td>
<ul>
<li>
#Html.ActionLink("Edit", "EditImage", new { controller = "Edit", brand = image.Collection.Brand.Name,
season = image.Collection.Season, imageId = #image.Id } )
</li>
<li>
#Html.ActionLink("Delete", "DeleteImage", new
{
controller = "Edit",
brand = image.Collection.Brand.Name,
season = image.Collection.Season,
imageId = #image.Id
})
</li>
</ul>
</td>
</tr>
}
</table>
<p>
<input type="submit" value="Save Changes" class="save-order" id="saveTable-#collection.Id"/>
</p>
}
Here is the jQuery so far:
$(document).ready(function () {
$(".table-collection").tableDnD();
$(".save-order").click(function (e) {
e.preventDefault();
$.ajax({ url: window.location.href,
type: 'POST',
data: { ids: $("--ASSIGN ARRAY HERE--"
});
The jQuery to iterate through each row is essentially this:
function(table, row) {
var rows = table.tBodies[0].rows;
var debugStr = "Row dropped was "+row.id+". New order: ";
for (var i=0; i<rows.length; i++) {
debugStr += rows[i].id+" ";
}
I see you are using input type submit which is exclusively used to postback forms. What you need to do is wrap every table up in a form with something like this:
#using(Html.BeginForm("Action", "Controller", new{ collectionId = collection.Id }))
{
<input type="submit" value="Save Changes" class="save-order" />
}
Note that this will cause a 'post-back' of the form to Action, Controller. Specify the collection id inside the route values to identify the specific collection.
Do note, you need to add input type hidden with the id's value otherwise the ids' won't get serialised - all you have to specify is the name attribute
<td class="dragHandle showDragHandle">
<input type="hidden" name="ids" value="#(image.Id)" />
#image.Id
</td>
Then you can intercept the call then do it via ajax with:
$(".save-order").click(function(e) {
e.preventDefault();
var form = $(this).closest('form');
if(form.validate()) {
$.post(form.attr('action'), form.serialize(), function() {
alert('The new image order has been saved.');
});
}
return false;
});
The accepting controller action method will probably have this signature
public ActionResult Action(int collectionId, int[] ids)
{
//Do stuff here
return Request.IsAjaxRequest() ? null : View();
}
Now it should support graceful degradation if javascript is disabled (does a normal form submit, otherwise does it via ajax)
Hope this helps :)
You can grab all of the IDs with something like this:
var IDs = [];
$("#mydiv").find("span").each(function(){ IDs.push(this.id); });
In your scenerio, do something like this:
$(document).ready(function ()
{
$(".table-collection").tableDnD();
$(".save-order").click(function (e)
{
var IDs = [];
$("#yourtable").find("draggable-tr-class").each(function(){ IDs.push(this.id); });
e.preventDefault();
$.ajax(
{
url: window.location.href,
type: 'POST',
data: { ids: IDs }
);
}
})
i have been create demo in jsfiddle using json
http://jsfiddle.net/viyancs/4ffb3/11/
if you use like that demo in your server must be get parameter `JSONFile' after that parse this json for what do you want.actually the demo not same with your case but i think you can use this by your logic.

Categories