I am trying to fetch a set of data from controller to view, I have the following;
Index.cshtml
<input type="button" value="submit" class="btn btn-default" id="btnGet" name="btnGet" onclick="displayCalendar()" />
Upon pressing the button, the displayCalendar() function calls the jQuery fullCalendar which populates all the events from the controller.
The problem is that I have a set of integers that I also want to be fetched in that AJAX call or separately.
Controller:
return Json(totalList, JsonRequestBehavior.AllowGet);
Now what have I tried?
I tried using ViewBag, ViewData, TempData. like this;
TempData["countWeekDays"] = countWeekDays;
TempData["countPresents"] = countPresents;
TempData["countAbsence"] = countAbsence;
TempData["countLates"] = countLates;
TempData["countFines"] = countFines;
and then display them in the same Index.cshtml but it did not work. I, then made a list of integers and tried to bind that list along with the already list of objects that was passed in the json like;
List<int> statsView = new List<int>();
statsView.Add(countWeekDays);
statsView.Add(countPresents);
statsView.Add(countAbsence);
statsView.Add(countLates);
statsView.Add(countFines);
IEnumerable<object> completeObjects = totalList.Cast<object>().Concat(statsView.Cast<object>());
return Json(completeObjects, JsonRequestBehavior.AllowGet);
When I tried the above method, I could see the list in the console debug in the browser but the problem is that it doesnt populate the calendar then. if I exclude the list statsView then the calendar is properly populated with the events.
Maybe a function within the displayCalendar() that is when called, it fetches the list from the controller and simply displays it in the view?
UPDATED:
<div id='calendar'></div>
#section scripts{
<script>
function h() {
id = $('#EmpId').val();
s = $("#startDate").val();
e = $("#endDate").val();
$.post("/Controller/method",
{
ENum: id,
StartDate: s,
EndDate: e
},
function (response) {
callCalendar(response);
}
);
}
function displayCalendar(e)
{
$("#calendar").fullCalendar('removeEvents');
$("#calendar").fullCalendar('addEventSource', e);
$("#calendar").fullCalendar('rerenderEvents');
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaDay'
},
}
});
//stats here
}
</script>
<script>
$(document).ready(function () {
displayCalendar('');
});
</script>
}
If your current code is working to correctly populate the calendar and if you want to send some additional data (list of integers), you may return a new annonymous object with 2 properties, one for your original data and second for the additional data.
List<int> statsView = new List<int>();
statsView.Add(countWeekDays);
statsView.Add(countPresents);
statsView.Add(countAbsence);
statsView.Add(countLates);
statsView.Add(countFines);
return Json(new { list = totalList, statusList = statsView },
JsonRequestBehavior.AllowGet);
Now make sure you update the client side code to use the list property of the response object for your callCalendar method call. To get the statusView collections, use the statusList property of the response object.
var d = { ENum: id, StartDate: s, EndDate: e };
$.post("/Controller/method",d ,function (response) {
console.log(response.statusList);
callCalendar(response.list);
});
If you want to display the items in response.statusList in the page, you may loop through them and add it to any existing DOM element. You can use $.each for iterating the array.
$.post("/Controller/method",d ,function (response) {
console.log(response.statusList);
var items="";
$.each(response.statusList,function(a,b){
items+='<p>'+b+'</p>';
});
$("#StatusList").html(items);
callCalendar(response.list);
});
Assuming you have a div with id set to StatusList in your page
<div id="StatusList"></div>
Related
I'm unsure if this is possible but I want to use jQuery to assign value from my bound model to different textboxes inside a PartialView.
Originally when the page loads, it populates correctly with all of the model information. However I would like to implement a DDL to view historical updates (retrieved from my pre-populated DB).
I am able to call an Action method inside my respective controller which accepts a revisionID. I have verified that the method is returning the correct data.
Please see below for my code snippets:
Partial View:
$('#revisionDDL').change(function () {
var selectedRevisionID = $(this).val();
if (selectedRevisionID == '') {
selectedRevisionID = #Model.RevisionID - 1;
}
var url = '#Url.Action("GetAgreementByRevision")';
$.get(url, { revisionID: selectedRevisionID }, function () {
$('#ChangeReason').val('#Model.ChangeReason');
})
});
Input element:
<div class="input-group">
<span class="input-group-addon" id="change-reason">Change Reason</span>
#Html.TextAreaFor(m => m.ChangeReason, new { #class = "form-control", #rows = "1" })
</div>
Controller method:
public ActionResult GetAgreementByRevision(int revisionID)
{
Agreement revisedAgreement = new Agreement();
revisedAgreement = _agreementService.GetAgreementDetailsByRevision(revisionID);
return PartialView("AgreementDetailsFormPartial", revisedAgreement);
}
If I am not able to accomplish this, what would be my other options?
Your method in the controller returns PartialView which returns HTML content and you're trying to pass that HTML content as a value in the text area - this is not how it should work. You should return Json(revisedAgreement, JsonRequestBehavior.AllowGet); and then access this object in JavaScript.
$.get(url, { revisionID: selectedRevisionID }, function (data) {
// 'data' is your Agreement object
$('#ChangeReason').val(data.SomePropertyHere);
});
In my web site I'm getting data from xml in first controller action method and display as dropdown (html select and option).When a user selects an item in first dropdown, selected item sent to the next view's controller as a parameter using jquery $.post. I have keep breakpoints and see what is going on. Data trasfer is success until second view . But display nothing. I have attached screenshot of my break points and codes.
This is my controllers.
public ActionResult First()
{
//get the location data
var Loc = getData("Location", "", "", "");
List<FirstData> Ilc = new List<FirstData>();
foreach(var val in Loc)
{
Ilc.Add(new Firstdata
{
Destination = val
});
}
ViewBag.Loc = Ilc;
return View();
}
this is how I pass data from first view to second action controller method
<script type:"text/javascript">
$(document).ready(function() {
$("#chk a").addCIass("btn btn-default");
$("#chk a").click(function () {
var url = '#Url.Action("Check","Cruise")';
$.post(url, { LocNane: $("#desti").val() }, function (data) {
//alert("succes");
});
});
});
</script>
this is how my second controller gets pass data[I made a breakpoint here]
public ActionResult Check(string LocName)
{
string d = LocNane;
var Nan = getData('Location',"Name",d,"");
List<Seconddata> nf = new List<Seconddata>();
foreach (var val in Nam)
{
nf.Add(new Seconddata
{
Naneof = val
});
}
ViewBag.Nn = nf;
}
and this is my second view and display data in break point
<body>
<div>
#foreach( var item in #VieuBag.Nm)
{
<h3>one</h3>
}
</div>
</body>
I put "#item.Nameof" inside the header tags , but it didn't work. so just to chek I put one. after go through the loop nothing display.what's the wrong.please help me with this.
The problem here is the success handler of $.post does not append/insert the returned html in any element. You can do something like this in success handler where divId is element Id in page where you want to show the returned html.
$("#divId").append(data);
I am working on an MVC EF site that has a SQL DB with two tables:
Entries, Members.
Moderators of the site can assign tasks to Members which will be logged in Entries.
I'm trying to determine a way to prioritize the Members list so that the Member with the least amount of tasks (as an always-incrementing number) will always OrderBy from the top so that the Moderators can assign based on who has taken the least amount of tasks.
I explored doing this in the DB itself: I can create a View that will check the Entries against the names on Members and provide a total of how many tasks they have been assigned. However; EF/dbContext doesn't work with SQL Views apparently.
I have an EntryController which feeds the Entries Table into the View and a MemberController which simply lists the members. My next thought is to simply call an action in the MemberController that increments a specific Member's count number when called. I'm not sure if this is the best way to do this or how I can even call both the Input-Submit POST from the Html.BeginForm and the Increment function at the same time.
The BeginForm is on a strongly-typed view of the EntryController so I'm also not sure how I could pass a Member back to the member controller so instead I made the function to identify the member based on a string grab .first and increment:
public void incrementCount(string member)
{
Member[] members = null;
members[0] = (repository.Members.Where(p => p.Name == member).First());
members[0].Count = members[0].Count + 1;
}
I am completely lost at this point so any suggestions would be greatly appreciated.
Sounds to me that you're lost on all 3: EF, ASP.NET MVC and Linq.
IMHO you should send a HTTP POST or a HTTP PATCH (depends on both context & interpretation) request with jQuery (or other) back to your server/controller which will then increment the task count for the member.
Your controller would, then, have a method Increment(int memberId) with a route like [Route("/lorem/ipsum/members/increment/{id}")] so you can access it from client-side.
This is an interesting approach rather than a full form post to the server because you can send only relevant data (only the memberId instead of the whole form and receive nothing, instead of a whole new page), reducing server load and increaing performance.
Now, for the link, you can either use the regular syntax as Brendan posted ot the Linq bellow, which should be fine too:
var memberId = repository.Entries
.GroupBy(_entry => _entry.MemberId)
.Select(_group => new { Id: _group.Key, Count: _group.Count() })
.OrderBy(_group => _group.Count)
.First().Id;
Some samples to illustrate possible approaches
First, this will be our controller/method on ASP.NET MVC:
[RoutePrefix("Lorem/Ipsum/Task")]
public class LoremController : Controller
{
[Route("Increment"), HttpPost]
public JsonResult Increment(int id)
{
try
{
// Increment your task count!
return Json(new { Success = true, ErrorMessage = "" });
}
catch(Exception err)
{
return Json(new { Success = false, ErrorMessage = err.Message });
}
}
}
Sample with jQuery
<div class="blabla">
<button id="btnIncrement" class="btn btn-primary" type="button" data-member-id="1">
Increment!
</button>
</div>
<script>
$("#btnIncrement").on("click", function() {
var _this = $(this);
$.ajax({
url: "/lorem/ipsum/task/increment",
data: { MemberId: _this.data("member-id") },
method: "POST",
success: function(json) {
if (json.Success) alert ('Success!');
else alert(json.ErrorMessage);
},
error: function () { alert("error!); }
});
});
</script>
Sample using a simple form (non-jquery/javascript)
<form action="/lorem/ipsum/task/increment" method="POST">
<input type="hidden" name="MemberId" value="1" />
<button type="submit" class="btn btn-primary">Increment!</button>
</form>
Sample with Angular.JS
<div ng-app>
<button ng-controller="lalaController" ng-click="increment(1)" class="btn btn-primary" type="button>
Increment!
</button>
</div>
<script>
angular.controller("lalaController", ["$scope", "$http", function($scope, $http) {
$scope.increment = function(id) {
$http({ url: "/lorem/ipsum/task/increment", data: { MemberId: id }, method: POST })
.success(function(json) {
if (json.Success) alert ("Success!");
else alert(json.ErrorMessage);
})
.error(function() { alert("Error!"); });
}
}]);
</script>
Sure sounds much more interesting on going with pure HTML.
But now, try to disable that button unless it's a prime number. It will be impossible with pure HTML. Also, try to validate your input or parse the response (let's say: udpate your grid on the page with a JSON array of new values)...
You can do this via Linq:
var query = from e in repository.Entries
group e by e.MemberId into g
select new
{
name = g.Key,
count = g.Count()
};
Will return a list of member id's along with the number of Entry records they have.
Well I have simple ajax form:
This is MyPartialView
#using(Ajax.BeginForm("action", "controller", new AjaxOptions
{
OnBegin = "beginRequest",
OnComplete = "completeRequest",
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "div-to-replace"
}, }))
{
<input type="text" id="my-input" />
...
}
This is parent view:
<div id="div-to-replace">
#Html.RenderPartial("MyPartialView")
</div>
In my controller I have:
[HttpPost]
public ActionResult action(Model model)
{
if (ModelState.IsValid)
{
// do staff with model
// return partial view
return PartialView("MyPartialView");
}
// else add error and return json result
return Json(new {error = "invalid data"});
}
And my javascript on ajax complete method:
function completeRequest(data) {
var result = $.parseJSON(data.responseText);
if (result != 'undefined' && result != null && result.error) {
// just display error and not replace all content
// attachModelError is my custom method, it just adds vlaidation-error class to inputs, etc.
attachModelError("my-input", result.error);
return;
}
// or show returned html (depending on returned model form inputs will be modified:
// select box with different items in my case
$('#div-to-replace').html(data.responseText);
}
But the problem is I have empty #div-to-replace if model state is invalid. If model state is ok every thing works fine. If I use different insertion mode it creates duplicates of div's content before or after div.
Summary:
I want different InsertionMode behavior depending on json result. I don't need replace data if (result != 'undefined' && result != null && result.error).
I had to solve this problem once so very long ago. I came up with a simple solution, which today, may not be the best solution but it gets the job done.
My solution involved setting up a controller action that would render just the partial with data that it would need and have my JavaScript request it.
C#
MyController: Controller
{
public ActionResult GetPartialViewAction()
{
return PartialView("mypartialview", new partialViewModel());
}
}
JavaScript
$.ajax({
url: "/my/getpartialaction/"
}).done(function(data) {
$("#partialViewDiv").html(data);
});
HTML
<div id="partialViewDiv"></div>
A better solution would be to use a MVVM/MVC JavaScript library that would allow you to leverage html templates and only have to transmit the data over your ajax solution. I recommend looking into knockout.js or backbone.js for this more accepted pattern.
I have the same problem with the default c# ajax forms. I have a solution what might work.
jQuery:
$(function () {
var ajaxFormSubmit = function () {
var $form = $(this);
var options = {
url: $form.attr("action"),
type: $form.attr("method"),
data: $form.serialize(),
cache: false
}
$.ajax(options).done(function (data) {
data.replaces.each(function (replace) {
$(replace.id).replaceWith(replace.html);
});
});
return false;
};
$("form[data-ajax='true']").submit(ajaxFormSubmit);});
form.cshtml
#using (Html.BeginForm("Create", "Menu", FormMethod.Post, new { data_ajax = "true" }))
{}
model sample
public string Id {get;set;}
public string Html {get;set;}
The last thing you need to do in your controller is return a json result with a list of your model sample, id is target element to update, for the html you must use a render partial / or view as string.
For render view to partial see [question]: https://stackoverflow.com/questions/434453
I have a list of Payees in a drop down box on my form. I would like to populate a different drop down, based on the selected item of the Payee drop down, without post backs and all that.
So, I created a method in my controller that does the work:
private JsonResult GetCategories(int payeeId)
{
List<CategoryDto> cats = Services.CategoryServices.GetCategoriesByPayeeId(payeeId);
List<SelectListItem> items = new List<SelectListItem>();
foreach(var cat in cats)
{
items.Add(new SelectListItem {Text = cat.Description, Value = cat.CategoryId.ToString()});
}
return Json(items);
}
Now, I am unsure what to add to my view to get this to work.
At the moment, all I have is this:
<% using (Html.BeginForm())
{%>
<p>
<%=Html.DropDownList("SelectedAccountId", Model.Accounts, "Select One..", null) %>
</p>
<p>
<%=Html.DropDownList("SelectedPayeeId", Model.Payees, "Select One...", null) %>
</p>
<input type="submit" value="Save" />
<%
}%>
they populate fine... so when the user selects the SelectedPayeeId drop down, it should then populate a new (Yet to be created?) drop down which holds categories, based on the SelectedPayeeId.
So, I think I need to create a JQuery function (Never done JQuery.. so not even sure where it goes) which monitors the Payee drop down for an onChange event? And then call the method I created above. Does this sound right, and if so, can you guide me in how to achieve this?
Your reasoning so far is totally sound. First you are going to want to include the jquery library in your View / Master. You can download a copy of jquery from http://jquery.com/. Add the file to you project and include a <script src="/path/to/jquery.js"> to the <head> of your document. You are going to want to add another dropdown to your View (and probably another property to your model). We'll call this 'SelectedCategoryId:'
<%=Html.DropDownList("SelectedCategoryId", null, "Select One...", new { style = "display:none;"}) %>
We've set the style of this Drop Down to not be visible initially because there is nothing to select inside of it. We'll show it later after we generate some content for it. Now, somewhere on your page you will want to include a <script> block that will look something like this:
$(document).ready(function() { $('#SelectedPayeeId').change(function() {
$.ajax({
type: 'POST',
url: urlToYourControllerAction,
data: { payeeId: $(this).val() },
success: function(data) {
var markup = '';
for (var x = 0; x < data.length; x++ ) {
markup += '<option value="' + data[x].Value + '">'+data[x].Text+'</option>';
}
$('#SelectedCategoryId').html(markup).show();
}
}); }); });
This code binds the anonymous function written above to the DOM element with the ID of 'SelectedPayeeId' (in this case your dropdown). The function performs an AJAX call to the url of your method. When it receives the results of the request (your JSON you returned) we iterate over the array and build a string of the html we want to inject into our document. Finally we insert the html into the 'SelectedCategoryId' element, and change the style of the element so it is visible to the user.
Note that I haven't run this code, but it should be (almost) what you need. jQuery's documentation is available at http://docs.jquery.com/Main_Page and the functions I used above are referenced here:
.ready()
.change()
jQuery.ajax()
.html()
.show()
You'd need to make the GetCategories as a public method as it would correspond to an action handler in your controller.
Your jquery code can look like:
<script type="text/javascript">
$(function() {
$('#SelectedPayeeId').change(function() {
$.get('<%= Url.Action("GetCategories", "YourControllerName") %>',
{payeeId: $(this).val()},
function(data) {
populateSelectWith($("#Category"), data);
});
});
//Place populateSelectWith method here
});
</script>
The populateSelectWith can fill your dropdown with data like:
function populateSelectWith($select, data) {
$select.html('');
$select.append($('<option></option>').val('').html("MYDEFAULT VALUE"));
for (var index = 0; index < data.length; index++) {
var option = data[index];
$select.append($('<option></option>').html(option));
}
}
I have not tested this code, but I am hoping it runs okay.
You can find syntax for the jquery ajax get here
Since you are not posting any data to the server, you can might as well decorate your controller action with a [HttpGet] attribute