List of MVC Ajax links only update page once - c#

I have a list of Ajax links that are created by the code below.
It displays a name with a link "remove" next to it.
When clicked, I want the name/link removed from the list.
Problem: I can only click and update the page once.
After clicking one of the Ajax links which removes it from the list,
it won't let me click another link. I click and it doesn't do anything.
If I want to click and remove another link, I have to refresh the page.
I don't really know javascript but I'm guessing it has to do with the name or id of the element being the same.
<table cellspacing="4" cellpadding="4" border="1" width="750">
#foreach (var item2 in Model.PeopleCheckBoxes)
{
if (ctr == 3)
{
#:<tr>
}
<td><img src="icon.jpg"> </td>
<td valign="middle" align="left">
#item2.Username
#item2.Username
#Ajax.ActionLink("remove", "RemoveMemberFromEvent", "GiftList",
new { eventID = #Model.catID, peopleID = #item2.Id },
new AjaxOptions
{
UpdateTargetId = "peopleTable",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST"
}, new { #class = "details2", title = "Remove person" })
</td>
if (ctr == 5)
{
#:</tr>
ctr = 2;
}
ctr++;
} </table>
[HttpPost]
public PartialViewResult RemoveMemberFromEvent(int eventID, int peopleID)
{
// removes item :
var aEvent = (from p in _EventMemberRepository.Table
// ............
_giftListService.DeletePersonOnGiftPage(aEvent);
// then update the database :
var members2 = from c in _custRepository.Table
var vModel = new GiftListItems();
//...........
return PartialView("_RemoveMemberFromEvent", vModel);
}
Is this a common problem?

Related

Use Ajax to update the value of two dropdowns filters C# MVC

i've developed an mvc web app where i have a table with datas that i can filter with two dropdowns (one where i can select the value state of a data, and the other where i can select the value if the data is closed or not - yes/no) i can select both of them and if i press the button submit to filter it works. Now i want to implement some ajax calls like when i select a value of one of the dropdowns automatically update the result table but i can't pass the value of the dropdown to the controller, can anyone help me, thanks
<table id="tb2">
<tr>
<th>
<h4> LIST : #Html.DropDownList("stato", "ALL ")</h4>
</th>
<th>
<h4>ARCHVIED : #Html.DropDownList("closed", "ALL ")</h4>
</th>
<th>
<input type="submit" value="Filter" class="btn btn-info" />
</th>
</tr>
</table>
This is the controller:
public ActionResult Filter(string stato, string closed)
{
List<Card> cards = new List<Card>();
List<Closed> closedList = new List<Closed>();
closedList.Add(new Closed("False"));
closedList.Add(new Closed("True"));
ViewBag.stato = new SelectList(myApi.GetState(), "Name", "Name");
ViewBag.closed = new SelectList(closedList, "Id", "Name");
if ((stato != null && stato != "") || (closed != null && closed != ""))
{
foreach (var card in model)
{
if (card.IdList == stato || stato == "")
{
if (card.Closed == closed || closed == "")
{
cards.Add(card);
}
}
}
return View(cards);
}
return View(model);
}
this is my jquery
jQuery(document).ready(function ($) {
var drpdown1 = $("#Dropdown1Id");
var drpdown2 = $("#Dropdown1Id");
drpdown1.on('change', function () {
$.ajax({
type: "GET",
url: " /Select/Filter",
data: { stato: drpdown1.val(), closed: drpdown2.val() },
success: function (res) {
var dropValue1 = drpdown1.val();
var dropValue2 = drpdown2.val();
stato = dropValue1;
closed = dropValue2;
}
})
})
});
But it's not working, i'm new to ajax and need some help
Change your html give a method on button click. Give Id for both drop down and then write ajax function like bellow
function YourMethod() {
var drpdown1= $("#Dropdown1Id").val();
var drpdown2= $("#Dropdown2Id").val();
$.ajax({
type: "GET",
url: "/ControllerName/Filter",
data: { stato: drpdown1,closed:drpdown2},
success: function(res) {
//Your work here
}
})
}

Asp.NET unique item in list validaton

I have view with tasks. Each task has an #Ajax.Action link to add this task to check list.
My view:
#foreach (var item in Model.Tasks) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.TaskText)
</td>
<td>
#Html.DisplayFor(modelItem => item.TillDate)
</td>
<td>
#Html.EnumDropDownListFor(modelItem => item.State, new { id=item.Id, #class="state"})
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
#Ajax.ActionLink("Add To check list", "AddToCheckList", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "CheckListPartial" });
</td>
</tr>
}
My controller action:
public PartialViewResult AddToCheckList(int id)
{
context.AddTaskToCheckList(id);
return PartialView("_LoadCheckList", context.CheckList);
}
And CheckList class:
public class CheckList
{
public string Name { get; set; }
public List<Task> Tasks { get; set; } = new List<Models.Task>();
}
Now adding works, but I have a problem: I can add one task to check list several times.
How can I validate if check list contains task and show error message?
UPD:
I've make this with my controller. Validation works, but message is not shown.
public PartialViewResult AddToCheckList(int id)
{
if(context.CheckList.Tasks.Exists(t=>t.Id==id))
ModelState.AddModelError("CheckList", "Check list already contains this task.");
if (ModelState.IsValid)
{
context.AddTaskToCheckList(id);
return PartialView("_LoadCheckList", context.CheckList);
}
return PartialView();
}
Also add this string to my View:
#Html.ValidationMessageFor(model => model.CheckList)
UPD2:
My PartialView:
#model TaskTracker.Models.CheckList
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
Текст задания
</th>
<th>
Дата выполнения
</th>
<th></th>
</tr>
#foreach (var task in Model.Tasks)
{
<tr>
<td>
#Html.DisplayFor(modelItem=>task.Value.TaskText)
</td>
<td>
#Html.DisplayFor(modelItem => task.Value.TillDate)
</td>
</tr>
}
</table>
You cannot display a ModelState error from a partial in the main view's #Html.ValidationMessageFor() - that is razor code and is parsed on the server before its sent to the view, so will display ModelState errors from the main views model only.
One option would include moving the ValidationMessageFor() to the partial view with the only drawback being the ability to position the element.
However, returning the whole table of added tasks is unnecessary when you already know all the values in the client to append the new row to the table.
Change your code to use the $.ajax methods and in the method return a JsonResult indicating success or otherwise
Html
Add To check list
Script
var url = '#Url.Action("AddToCheckList")';
var table = $('#CheckListPartial table);
$('.add').click(function() {
var id = $(this).data('id');
var cells = $(this).closest('tr').find('td');
var text = cells.eq(0).text();
var date = cells.eq(1).text();
$.post(url, { id: id }, function(result) {
if (result) {
// create and append a new row
var row = $('<tr></tr>');
row.append($(<td></td>).text(text));
row.append($(<td></td>).text(date));
table.append(row);
} else {
// display your error
}
}).fail(function (result) {
// display your error
});
})
and the controller method would be
public JsonResult AddToCheckList(int id)
{
if(context.CheckList.Tasks.Exists(t => t.Id == id))
{
return Json(null); indicate error - show a hidden element containing a message
}
context.AddTaskToCheckList(id);
return Json(true); // indicate success
}
You should also consider removing the link if successful, so the user does not accidentally click it again.
A third alternative would be to generate a checklistbox of all tasks and allow the user to select or unselect items and the post a form and save all taks inone action. Refer this answer for an example of the approach.
You can make your Tasks to be an HashSet and check in the AddTaskToCheckList method if it is already there. In that case checking is O(1)
public void AddTaskToCheckList(int id)
{
// Find task
var task = this.Tasks.Find(id);
if(!this.CheckList.Contains(task))
{
this.CheckList.Add(task);
}
else
{
// Show error message
}
}

Pass Data from controller to view is not responding. Is there something wrong in the code?

The website I am coding is working fine except for the remove from cart option. I don't get any error in the code but when I click the link for remove from cart the code does nothing. It seems as if the page just refreshes. I am coding the system in C#.net MVC 4. Please can someone help me.
This is part of the ShoppingCartController.cs
[HttpPost]
public ActionResult RemoveFromCart(int id)
{
// Remove the item from the cart
var cart = ShoppingCart.GetCart(this.HttpContext);
// Get the name of the album to display confirmation
string albumName = storeDB.Carts
.Single(item => item.RecordId == id).Album.Title;
// Remove from cart
int itemCount = cart.RemoveFromCart(id);
// Display the confirmation message
var results = new ShoppingCartRemoveViewModel
{
Message = Server.HtmlEncode(albumName) +
" has been removed from your shopping cart.",
CartTotal = cart.GetTotal(),
CartCount = cart.GetCount(),
ItemCount = itemCount,
DeleteId = id
};
return Json(results);
}
This is part of the ShoppingCart model.
public int RemoveFromCart(int id)
{
// Get the cart
var cartItem = storeDB.Carts.Single(
cart => cart.CartId == ShoppingCartId
&& cart.RecordId == id);
int itemCount = 0;
if (cartItem != null)
{
if (cartItem.Count > 1)
{
cartItem.Count--;
itemCount = cartItem.Count;
}
else
{
storeDB.Carts.Remove(cartItem);
}
// Save changes
storeDB.SaveChanges();
}
return itemCount;
}
Lastly this is the ShoppingCart/Index view.
#foreach (var item in Model.CartItems)
{
<tr id="row-#item.RecordId">
<td>
#Html.ActionLink(item.Album.Title, "Details", "Shop", new { id = item.AlbumId }, null)
</td>
<td>
#item.Album.Price
</td>
<td id="item-count-#item.RecordId">
#item.Count
</td>
<td>
Remove from cart
</td>
</tr>
}
Unless you've got some javascript somewhere that is handling the onclick of your "Remove from cart" link or adding an href to it, your current href of "#" will 'seem to refresh the page' exactly as you've described. Consider changing that anchor tag to an ActionLink like your Details link but that points to your RemoveFromCart action method.
You need to use Html.ActionLink instead of a tag, just like you do for Shop/Details action. Example (assuming that your RemoveFromCart action is in ShopController and you want to delete an item with id = item.AlbumId):
#Html.ActionLink(
"Remove from cart",
"RemoveFromCart",
"Shop",
new { id = item.AlbumId },
new { #class = "RemoveFromCart"})
This way full page refresh will be performed and you will need to return View from your action. To make only partial refresh you will need to use Ajax.ActionLink helper.

Reload partial view with a button in the partial view

i use mvc 4 and try to give my web application more dynamic. At the moment i try to split some of the views in partial views so the code gets better readable and i can better re-use parts of the application.
So now this leads me to a problem. I have a view similar to this one:
<h1>Manage department</h1>
<div id="EmployeesManagement">#Html.Action("OpenEmployeesManagement")</div>
<div id="DepartmentManagement">#Html.Action("OpenDepartmentManagement")</div>
<div id="DepartmentTumorModels">#Html.Action("OpenDepartmentModels")</div>
Each of those are partial views which get called from the controller like:
public PartialViewResult OpenDepartmentModels()
{
ViewBag.ChangeVisibility = -1;
HoDManagementModel hoDManagementModel = new HoDManagementModel { UserWithRoleModelList = azaraUserManagement.GetAllEmployesOfHoD(user.getUserId()), OrganisationUnits = azaraUserManagement.GetAllOrganisationUnitsFromHoD(user.getUserId()) };
List<ModelWithOrganisationUnit> Models = ModelManagement.SearchModelsOfDepartment(hoDManagementModel.OrganisationUnits);
return PartialView("DepartmentModels", Models);
}
Now to my problem. I have a partial view like this one:
#model List<Modelle.Models.BusinessTierObjects.Models.ModelWithOrganisationUnit>
<fieldset>
<legend>Manage the models of your department</legend>
<table class="tablesorter">
<thead>
<tr>
<th>ID</th>
<th>Name </th>
<th>Department </th>
<th>Visibility</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in #Model)
{
<tr>
<td>#item.ModelId</td>
<td>#Html.ActionLink((String)item.ModelName, "Details", "Details", new { id = item.ModelId }, null)</td>
<td>#item.OrganisationUnitName</td>
#if (ViewBag.ChangeVisibility == item.ModelId)
{
<td><select name="ChangeVisibility" id="ChangeVisibility">
<option value="Department" onclick="location.href='#Url.Action("ChangeVisibility", "ManageDepartment", new {tumorModelId = item.ModelId, Visibility = 0})'">Department</option>
option value="Coop" onclick="location.href='#Url.Action("ChangeVisibility", "ManageDepartment", new { ModelId = item.ModelId, Visibility = 2 })'">Coop</option>
<option value="WWW" onclick="location.href='#Url.Action("ChangeVisibility", "ManageDepartment", new { ModelId = item.ModelId, Visibility = 3 })'">WWW</option>
</select></td>
}
else{
switch ((byte)item.Visibility)
{
case 0: <td>Department</td>; break;
case 2: <td>Coop</td>; break;
case 3: <td>WWW</td>; break;
}
}
<td><button name="button" class="button" onclick="location.href='#Url.Action("RequestChangeVisibility", "ManageDepartment", new { change = #item.ModelId })'">Change Visibility</button>
</td>
</tr>}
</fieldset>
and if i click on the last button just the partial view should be reloaded. But instead the application only show me the partial view without any layout in the browser. What have i done wrong or isn´t it possible to solve my problem?
The controller action from the button is:
public PartialViewResult RequestChangeVisibility(int change)
{
ViewBag.ChangeVisibility = change;
HoDManagementModel hoDManagementModel = new HoDManagementModel { UserWithRoleModelList = azaraUserManagement.GetAllEmployesOfHoD(user.getUserId()), OrganisationUnits = azaraUserManagement.GetAllOrganisationUnitsFromHoD(user.getUserId()) };
List<ModelWithOrganisationUnit> Models = ModelManagement.SearchModelsOfDepartment(hoDManagementModel.OrganisationUnits);
return PartialView("DepartmentModels", Models);
}
The reason this happens is because you are using:
onclick="location.href='#Url.Action("RequestChangeVisibility", "ManageDepartment", new { change = #item.ModelId })'"
This will refresh the whole page to the partial view result, so you only see that partial view.
what you need to do is to do an ajax call to that controller, so you should use:
<td><button name="button" class="button" onclick="RequestChangeVisibilityAjaxCall(#item.ModelId)">Change Visibility</button>
then add the following javascript to the page:
<script>
function RequestChangeVisibilityAjaxCall(change) {
$.ajax({
url: "../ManageDepartment/RequestChangeVisibility?Change=" + change,
type: 'GET',
success: function (data) {
$('#DepartmentManagement').html(data);
}
});
}
</script>
The line:
$('#DepartmentManagement').html(data);
will use the result of the ajax call (data) to populate the div with ID DepartmentManagement - I wasnt sure where you wanted that partial view to go, so just change the ID to what ever you need it to be.
Also, the line:
url: "../ManageDepartment/RequestChangeVisibility?Change=" + change,
is the url of the controller, I think i guessed it right, but you should change this to the correct address where needed.
I hope this helps.
Martyn
[edit] a good tutorial here:
also, do some googling for "mvc jquery ajax" that should also help you understand it. Much better than I can explain it! :)

Updating data from form using jquery

There are many topics with this title, but none have helped me resolve my issue. I am new to MVC and jQuery, so my guess is there is something syntactically wrong with my approach. Any help is greatly appreciated.
I have a web application where I have an upper and a lower section on my page (both divs). My goal is to select a record in the top div (user list) and have the bottom section display a list of challenge questions that the user can fill in answers for. The list below is injected in using jquery based on the record selected in the top grid. Here's the code I am using to do this.
View - javascript:
function editModeratorSecurity(aPersonId) {
$.ajax({
url: '/Admin/GetAdvSecurity/' + aPersonId,
type: 'POST',
progress: showModSearchProgress(),
success: function (result) {
AdvancedSuccess(result);
},
error: function (result) {
AdvancedFailure(result);
}
});
}
function showModSearchProgress() {
$("#ModeratorDetail").hide();
$("#progressMod").show();
}
function endModProgress() {
$("#progressMod").hide();
$("#ModeratorDetail").show();
}
function AdvancedSuccess(result) {
$('#ModeratorDetail').html(result);
endModProgress();
}
function AdvancedFailure(result) {
endModProgress();
}
Controller:
public PartialViewResult GetAdvSecurity(string id)
{
//ID is the iD from the person table
PersonModelBuilder pmb = new PersonModelBuilder(CurrentSession.AccountId);
PersonEditModel pers = pmb.GetPersonToEdit(new Guid(id));
if (pers != null)
{
AdvancedSecurityModel sec = new AdvancedSecurityModel();
UserModelBuilder umb = new UserModelBuilder();
//Need to get the ID from the login table - using the email address
UserModel selUser = umb.CurrentUser(pers.EmailAddress);
//Need to get the challenge questions/answers for the selected users
List<UserQuestionModel> theQ = umb.GetUserChallengeQuestions(selUser.LoginId);
sec.theUser = selUser;
sec.theQuestions = theQ;
return PartialView("_UserChallengeQuestions",sec);
}
else
{
return PartialView("_UserChallengeQuestions", new AdvancedSecurityModel());
}
}
So - this call to the controller returns the partial view and I am populating the list of questions using the following code in the partial view:
#model AdvancedSecurityModel
<form id="frmChallengeQuestions" class="inlineForm">
<div style="min-height: 100px; max-height: 400px;overflow: hidden" >
<table width="100%">
<tr>
<td align="right"><input type="button" value="Save Changes" onclick="ValidateAndSave()"/> </td>
</tr>
<tr>
<td>
#{
string sInstruction = "";
string isChecked="";
string isDisplay = "none";
if (Model.theUser.SecondLevelAuthReqd)
{
isChecked = "checked='true'";
isDisplay = "";
sInstruction = "<br> Please answer <strong>at least 5</strong> of the questions below to set up this feature...";
}
}
2nd Authentication <input type="checkbox" id="2ndAuth" onclick="javascript:ToggleQuestions()" #isChecked/>
<br /> Checking this means that you will be required to answer a random challenge question from the questions you answer in the<br/> list below each time you log in.
<span id="spnExplanation"></span>
<p> </p>
<div id="theQuestionsandAnswers" style="display: #isDisplay; max-height: 175px;overflow-y: scroll" >
<table width="100%">
#{
if (Model.theQuestions != null)
{
int iCount = 0;
foreach (UserQuestionModel ques in Model.theQuestions)
{
string theAnswer = "";
iCount += 1;
if (ques.UserAnswer != null)
{
NLxCommon.Encryption enc = new NLxCommon.Encryption();
theAnswer = enc.Decrypt256(ques.UserAnswer);
enc.Dispose();
enc = null;
}
<tr>
<td width="5%"> </td>
<td>#ques.QuestionText</td>
<td><input id="Answer_#iCount" type="text" value="#theAnswer" /></td>
<td>
<input id="UserQuestionId_#iCount" type="hidden" value="#ques.UserQuestionId">
<input id="QuestionId_#iCount" type="hidden" value="#ques.QuestionId">
<input id="UserId_#iCount" type="hidden" value="#Model.theUser.LoginId">
</td>
<td width="5%"> </td>
</tr>
}
}
}
</table>
</div>
</td>
</tr>
</table>
</div>
</form>
In the loop, I am naming my controls - input id="Answer_#iCount" - Where iCount is the number of the question - from 1 to x.
The input button is an attempt to save the changes I made to the answers of the questions listed. The javascript function is listed below.
var numQ = #Model.theQuestions.Count;
function ValidateAndSave() {
var NumAnswers = 0;
for (i=1;i<=numQ;i++) {
var answer = "#Answer_" + i.toString();
var theAnswer = $(answer).val();
if (theAnswer != "") {
NumAnswers += 1;
}
}
if (NumAnswers < 5) {
alert('You must answer at least 5 questions to enable this feature');
return false;
}
//Answered the right number of questions so SAVE
for (j=1;j<=numQ;j++) {
var uAnswer = "#Answer_" + j.toString();
var uUserQid= "#UserQuestionId_" + j.toString();
var uQuestionId= "#QuestionId_" + j.toString();
var uUserId = "#UserId_" + j.toString();
var theUAnswer = $(uAnswer).val();
alert(theUAnswer );
var theuUserQuestionId = $(uUserQid).val();
alert(theuUserQuestionId );
var theuQuestionid = $(uQuestionId).val();
alert(theuQuestionid);
var theuUserId = $(uUserId).val();
alert(theuUserId );
$.ajax({
url: '/admin/savechallengequestion',
type: 'POST',
data: {
UserQuestionId: theuUserQuestionId.toString(),
LoginId: theuUserId.toString(),
QuestionId: theuQuestionid.toString(),
UserAnswer: theUAnswer.toString()
},
contentType: 'application/json; charset=utf-8',
//progress: showModSearchProgress(),
success: insSuccess(data),
error: function () {
alert("error");
}
});
}
}
My goal with this was to loop through the answers, sending one ajax call per transaction .If someone could tell me how to do this in one call I'm willing to listen :)
The alerts all pop, showing the proper data, but when I get to the ajax call, the progress function gets called, but the ajax call never makes it to the server - I never even see it in Fiddler - like nothing happened. The controller method and the model expected are listed below - havent filled out the controller method yet - still trying to get this to fire.
Model:
public class UserQuestionModelSave
{
public string UserQuestionId { get; set; }
public string LoginId { get; set; }
public string QuestionId { get; set; }
public string UserAnswer { get; set; }
}
Controller:
[HttpPost]
public ActionResult SaveChallengeQuestion(UserQuestionModelSave aQuestionInfo)
{
UserModelBuilder umb = new UserModelBuilder();
if (ModelState.IsValid)
{
try
{
return Json(new { success = true });
}
catch (Exception)
{
return Json(new { success = false });
}
}
return Json(new { success = false });
}
If anyone has any ideas I would greatly appreciate it - this has stumped me for almost 2 days now....
If ajax request doesn't fire, then you should check console for javascript errors. BTW, there is no "inSuccess()" function in your code, which you use in this ajax call.

Categories

Resources