Loading MVC webgrid content second time not working - c#

We have a webgrid there i am trying to bind IDictionary. I dont have any issue in binding first time. I am facing difficulty in the second time. I am getting the result in the model and it not refreshing the grid content second time. Trying to populate the grid data by dropdown value change. First time i am loading on menu click.
Here is my controller code. In the result i have the list of values. I am facing issue in binding it in webgrid after ajax call second time.
public List<IDictionary> GetHotelingList(int floorId)
{
var model = new List<IDictionary>();
using (var context = new FloorContext())
{
try
{
model = ListHotelingByFloorId(context, floorId);
}
catch (Exception ex)
{
}
}
return model;
}
This is my ajax call
$("#floor").bind("change", function () {
var facilityId = parseInt($("#FacilityDropDown option:selected").val());
var floorId = parseInt($("#floor option:selected").val());
$.ajax({
type: 'POST',
url: '/Floor/GetHotelingList',
cache: false,
data: { floorId: floorId },
success: function (data) {
},
complete: function () {
},
error: function () {
if (facilityName.indexOf('-') != -1) {
$('#floor').empty();
return;
}
else
alert("error in generating floor");
}
});
});
Code for binding in the grid.
#using System.Dynamic
#model List<System.Collections.IDictionary>
#{
var result = new List<dynamic>();
foreach (var emprow in Model)
{
var row = (IDictionary<string, object>)new ExpandoObject();
var eachEmpRow = (Dictionary<string, object>)emprow;
foreach (KeyValuePair<string, object> keyValuePair in eachEmpRow)
{
row.Add(keyValuePair);
}
result.Add(row);
}
var grid = new WebGrid(result, rowsPerPage: 50, ajaxUpdateContainerId: "grdHoteling");
}
Any help please?
Thanks in advance

you have to make a container div in main view from where you call ajax and load result in that div:
<div id="GridContainer">
// load you view first time here
</div>
and on ajax call update content of this div in success call back of ajax:
success: function (data) {
$("#GridContainer").html(data);
}

Related

Update C# variable via Ajax?

I have got a page full of posts, I sort those posts before rendering it.
Now I have created a drop down so user's can sort the posts by newest or oldest.
The only problem is I don't know how to update the server-side variable through Ajax.
#{
var SortSelected = "";
var sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).Reverse().ToList();
if (SortSelected == "Most recent")
{
sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).Reverse().ToList();
}
else if (SortSelected == "Oldest")
{
sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).ToList();
}
}
I have removed other code which is irrelevant to make it cleaner.
That's my code for the posts, this is the Razor(html)
<div class="AnimatedLabel">
<select name="contact" class="tm-md-12">
<option id="hide-selector-dropdown" value=""></option>
#foreach (var item in FilterTypes)
{
<option value="#item">#item</option>
}
</select>
<label for="contact">Sort by</label>
<span class="tm-icon-arrow--right" id="selector-dropdown-arrow"></span>
</div>
This is how I tried to do it -
<script>
$('select').on('change', function () {
SortSelected = this.value;
});
</script>
But it is not updating the value, I have been told because it is server-side.
I know people will probably roast me for this question but I do not know any other solution so any help would be great!
I do not have much experience with .net/c#
Thanks!
Okay, so I just wanted to show you how you can achieve something like this using AJAX. As far as I have understood, you want to sort your posts list based on the selection from the user in the dropdown list that you have. Please refer to the code snippet below and let me know if you were able to get what you wanted regarding your requirement:
<script>
$('select').on('change', function () {
//SortSelected = this.value;
//First get the text of the selected item
var selectedText=$('#hide-selector-dropdown :selected').text();
//Now generate your JSON data here to be sent to the server
var json = {
selectedText: selectedText
};
//Send the JSON data via AJAX to your Controller method
$.ajax({
url: '#Url.Action("ProcessMyValue", "Home")',
type: 'post',
dataType: "json",
data: { "json": JSON.stringify(json)},
success: function (result) {
//Show your list here
if (data.success) {
console.log(data.sortedArticles);
}
else {
console.log("List empty or not found");
}
},
error: function (error) {
console.log(error)
}
});
});
</script>
Your Controller would look like:
using System.Web.Script.Serialization;
[HttpPost]
public ActionResult ProcessMyValue(string json)
{
var serializer = new JavaScriptSerializer();
dynamic jsondata = serializer.Deserialize(json, typeof(object));
//Get your variables here from AJAX call
var SortSelected= jsondata["selectedText"];
//Do something with your variables here. I am assuming this:
var sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).Reverse().ToList();
if (SortSelected == "Most recent")
{
sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).Reverse().ToList();
}
else if (SortSelected == "Oldest")
{
sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).ToList();
}
return Json(new { success = true, sortedArticles }, JsonRequestBehavior.AllowGet);
}
You can't change server variable value but you can use this for refresh your table.
<script>
$('select').on('change', function () {
$.get('/Url' , {sortBy:this.value}).done(function(result){
$('#yourTable').html(result);
}).fail(function(){
alert('Error !');
});
});
</script>
You can call web method in server side using ajax.
Use that method to update variable on server side

Cannot get Nested Content in SurfaceController and return as JSON in AJAX

I have run into this problem. I have a view which gets rendered like this:
#inherits Umbraco.Web.Mvc.UmbracoViewPage
#using MyProject.Web.Models;
#using ContentModels = Umbraco.Web.PublishedContentModels;
#{
Layout = "MasterPage.cshtml";
}
#Html.Partial("_HeroModule")
#foreach (var item in Model.GetPropertyValue<IEnumerable<IPublishedContent>>("generalContentCollection"))
{
var partialViewName = "_" + item.DocumentTypeAlias;
if (partialViewName == "_curtainsModule")
{
Html.RenderPartial("CurtainsModule", new CurtainsModuleModel(Model, item));
}
else
{
#Html.Partial(partialViewName, item);
}
The 'item' here is a nested content general collection. Inside of it there's another collection I need to reach called 'fabricsCollection' which is also Nested Content.
The problem with this is that when I go to a SurfaceController and do this the 'fabricsCollection' returns null probably because it's Nested Content:
[HttpPost]
public JsonResult GetFabrics(int data)
{
//gets the id of the actual page doctype
var page = Umbraco.TypedContent(data);
//fabricsCollection underneath returns null
var fabricsCollection = page.GetPropertyValue<IEnumerable<IPublishedContent>>("fabricsCollection");
return Json(fabricsCollection);
}
}
and the ajax call which works fine:
$(".clearAll-desktop").click(function () {
event.preventDefault;
var pageId = $(".curtains-module").attr('id');
var fabrics = "#Model.FabricsCollection.ToString()";
debugger;
console.log(pageId);
$.ajax({
url: '/umbraco/Surface/CurtainsModuleSurface/GetFabrics',
type: 'POST',
data: { data: pageId, collectionName: fabrics },
dataType: 'string',
success: function (data1) {
console.log('success');
}
});
return false;
})
I'm stuck here for a few days and I don't know what I'm doing wrong. Anyone with a clearer mind can pinpoint what I'm doing wrong?

Knockout ViewModel Update

I am new to Knockout and I am trying to update my ViewModel from an ajax call. This is what I have right now:
LoanDeductions.js
var deductionLine = function (deductionID, deductionName, amount) {
self = this;
self.deductionID = ko.observable(deductionID);
self.deductionName = ko.observable(deductionName);
self.amount = ko.observable(amount);
};
function LoanDeductions(deductions) {
var self = this;
self.loanDeductions = ko.observableArray(ko.utils.arrayMap(deductions, function (deduction) {
return new deductionLine(deduction.deductionID, deduction.deductionName, deduction.amount)
}));
// Operationss
self.removeLine = function (line) { self.loanDeductions.remove(line) };
};
and this is my scripts in my view:
#section scripts
{
<script src="~/Scripts/koModel/LoanDeductions.js"></script>
<script type="text/javascript">
var updateValues = function () {
$.ajax({
'url': '#Url.Action("UpdateDeductionValues","LoanApp")',
'data': { amount: $('.LoanAmount').val() },
'success': function (result) {// update viewmodel scripts here}
});
var viewModel = new LoanDeductions(#Html.Raw(Model.CRefLoansDeductions2.ToJson()));
$(document).ready(function () {
ko.applyBindings(viewModel);
$('.datepicker').datepicker();
$('.LoanAmount').change(function () {
updateValues();
};
});
});
</script>
}
So, in my view, I have a dropdown list with class name "LoanAmount" which when value is changed, it will perform an ajax call, send the selected loanAmount value to the server, recompute the deduction amounts, then the server returns a jsonresult that looks like this:
"[{\"deductionID\":1,\"deductionName\":\"Loan Redemption Fee\",\"amount\":53.10},{\"deductionID\":2,\"deductionName\":\"Document Stamp\",\"amount\":9.00}]"
Now what I wanted to do is use this json data as my new viewModel.
Can anyone show me the way how to do this, please note that I manually mapped my viewmodel and didn't used the ko mapping plugin.
Any help will be greatly appreciated. Thank you, more power!
EDIT (in response to Fabio)
function updateData() {
$.ajax({
url: '#Url.Action("UpdateDeductionValues","LoanApp")',
data: { amount: self.selectedLoanAmount() },
success: function (deductions) {
//load your array with ko.utils.arrayMap
ko.utils.arrayMap(deductions, function (deduction) {
return new deductionLine(deduction.deductionID, deduction.deductionName, deduction.amount)
});
}
});
}
Not sure If I understood your problem, but if you want to change model values outside of the class, you need to do something like this:
$(document).ready(function () {
var viewModel = new LoanDeductions(#Html.Raw(Model.CRefLoansDeductions2.ToJson()));
ko.applyBindings(viewModel);
$('.datepicker').datepicker();
function updateValues() {
//do you ajax call
//update the model using viewModel.loanDeductions(newItens);
};
$('.LoanAmount').change(function () {
updateValues();
};
});
EDIT 1 - Just to show how to use knockout without jquery.change
function LoadDeductions() {
//declare you properties
var self = this;
self.loanAmount = ko.observable('initialvalueofloanamount');
self.loanDeductions = ko.observableArray();
//create a function to update you observablearray
function updateData() {
$.ajax({
url: '#Url.Content('yourActionhere')' or '#Url.Action('a', 'b')',
data: { amount: self.loadAmount() },
success: function (deductions) {
//load your array with ko.utils.arrayMap
}
});
}
//everytime that loanAmount changes, update the array
self.loanAmount.subscribe(function () {
updateData();
});
//update values initializing
updateData();
};
$(function() {
ko.applyBindings(new LoadDeductions());
});
Bind the select in the HTML
<select data-bind="value: loanAmount"></select>
EDIT 2 - To your second problem
function updateData() {
$.ajax({
url: '/LoanApp/UpdateDeductionValues', //try to write the url like this
data: { amount: self.selectedLoanAmount() },
success: function (deductions) {
//load your array with ko.utils.arrayMap
self.loanDeductions(ko.utils.arrayMap(deductions, function (deduction) {
return new deductionLine(deduction.deductionID, deduction.deductionName, deduction.amount)
}));
}
});
}
Your success handler should look like this.
function(result){
self.loanDeductions(result);
}
Unless you are trying to append in which case it would be
self.loanDeductions(self.loanDeductions().concat(result));

mvc ajax refresh div method controller json

I have a method in the controller that return a ViewBag with Json.
public JsonResult FilterCheck(int id, int[] mycheck, string idprot)
{
ViewBag.Utenti = this.GetDbContext().utente.Include(s => s.cod_servizio_utente).Where(x => x.cod_servizio_utente.Select(l => l.id).Contains(5)).ToList();
return Json(ViewBag.Utenti, JsonRequestBehavior.AllowGet);
}
In the view I have this script function ajax, if this function have "success" i would refresh a div that include a foreach on the viebag.Utenti:
$.ajax({
type: "POST",
url: "#Url.Action("FilterCheck","Operatore")",
datatype: "json",
traditional: true,
data: { 'mycheck': mycheck, 'idprot': idprot, 'id': '#Model.id' },
success: function(data) {
var html = $(data).filter('#external-events').html();
$('#external-events').html(data);
}
});
<div id='external-events'>
#foreach (HAnnoZero.Repositories.utente item in ViewBag.Utenti)
{
<div class='col-lg-3'><div class='external-event'>#item.id- #item.cognome #item.nome</div></div>
} </div>
But dont work. How can do for refresh the foreach inside div id "external events"?Who could help me?
Firstly you do not need to assign the collection to ViewBag
public ActionResult FilterCheck(int id, int[] mycheck, string idprot)
{
var data = this.GetDbContext().utente.Include(......
// Build anonymous object collection to avoid circular reference errors
var response = data.Select(d => new
{
id = d.id,
cognome = d.cognome
// other properties as required
});
return Json(response);
}
Secondly you are returning JSON, not html, so in your success function you need to iterate through the properties and build your html (not sure what your properties are, so adjust as necessary)
success: function(data) {
$('#external-events').empty(); // clear existing items
$.each(data, function(index, item) {
var div = $('<div><div>'); // Create new element
div.text(item.id + ' ' + item.cognome); // Set inner text
$('#external-events').append(div); // add the new element
});
}
An alternative is to have the action method return a partial view containing the html and then use
success: function(data) {
$('#external-events').html(data);
}

How to delete multiple items in MVC with a single link?

Consider following:
Partial View:
<%= Html.ListBox("BlackList", Model.Select(
x => new SelectListItem
{
Text = x.Word,
Value = x.ID.ToString(),
Selected = Model.Any(y=> y.ID == x.ID)
}))%>
Main View:
<td><% Html.RenderPartial("GetBlackList", ViewData["BlackList"]); %></td>
Controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult DeleteWord(int[] wordIdsToDelete)
{
if (!ModelState.IsValid)
return View();
try
{
_wordManager.DeleteWord(wordIdsToDelete);
return RedirectToAction("WordList");
}
catch
{
return View();
}
}
Model (WordManager)
public void DeleteWord(int[] idsToDelete)
{
var dataContext = GetLinqContext();
var currentList = GetTabooWordList();
foreach (var id in idsToDelete)
{
foreach (var item in currentList)
{
if (item.ID == id)
{
dataContext.BadWords.DeleteOnSubmit(item);
}
}
}
dataContext.SubmitChanges();
}
The question is how correctly pass the parameter - idsForDel ?
I.E I have to pass a client data to the server?
<%= Html.ActionLink("Delete Selected", "DeleteWord", "AdminWord", new { wordIds = idsForDel })%>
I think this can be made by jQuery. Any ideas?
You can bind to an array using the Model Binding to a List
(Haacked.com Model binding to a list, here you can see how to bind complex types as well).
Although I'm not happy with code where I create elements
so I can serialize it in order to bind it to the controllers action input parameter, this code works just what you want:
<script type="text/javascript">
function DeleteWords() {
var el = $("<form></form>");
//for every selected item create new input element and insert it
//inside of temporarty created form element
var selItems = $('#BlackList option:selected').each(function(intIndex) {
//is important how you name input elements (as you can read in link I referenced)
el.append($('<input/>')
.attr({ type: "hidden", name: "wordIdsToDelete", value: $(this).val() })
);
});
//make an ajax call with serialized temporary form
$.ajax({
type: "POST",
url: "/YourController/DeleteWord",
data: $(el).serialize(),
// error: HandleUnespectedError,
success: function(response) {
//handle response }
});}
Hope this helps...
How about this code?
<%= Html.ActionLink("Delete Selected", "DeleteWord",
"AdminWord", new { id="send" })%>
<script type="text/javascript">
$(function() {
$("#send").click(function() {
$.post(
$("form:first").attr("action"),
$("#GetBlackList").serialize()
);
});
});
</script>
And, If two or more records are deleted, DeleteAllOnSubmit is good.
dataContext.BadWords.DeleteAllOnSubmit(
currentList.Where(item=>currentList.Containts(item.id)).ToList()
);

Categories