Using FullCalendar 5.11.3 in my ASP.Net Core MVC application I have a problem that events aren't displayed.
On debugging one can see that on calendar initialization the controllers action is correctly called and also the data that is returned is correct and follows the requirements (https://fullcalendar.io/docs/event-source-object)
JSON that is returned when accessing action directly
[{"id":1,"title":"Beata Kowal","start":"13-09-2022","allDay":true}]
Calendar is placed in a partial view (as in the code below) and used in home view (in the future I plan to use it in several views with different data sources).
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
events: {
url: '/Home/GetCalendarData',
success: function() {
alert("ok");
},
failure: function() {
alert("error");
}
}
});
calendar.render();
});
</script>
<div class="row">
<div id='calendar' />
</div>
In the HomeController there is an action responsible for getting data to be used for displaying events
// GET: Home/GetCalendarData
public JsonResult GetCalendarData()
{
List<Appointment> appointments = _context.Appointments
.Include(app => app.Employee)
.Include(app => app.Customer)
.ToList();
List<HomeIndexGetViewModel> appointmentsIndexViewModel = _mapper.Map<List<Appointment>, List<HomeIndexGetViewModel>>(appointments);
return new JsonResult(appointmentsIndexViewModel);
}
Calendar is rendering and the alert on success is also displayed. What is more in the developer mode there are no errors or warnings. Yet, events still don't display.
My initial guess:
It takes too long to fetch data from the database and before action returns its result calendar is rendered and events can't not longer be added. If so, then how can I change it to work in a desired way? Introduce JS callback?
The problem was with parsing the date. It was not capable to process the provided date format which was "dd-MM-yyyy". After changing to "yyyy-MM-dd HH:mm:ss" everything works fine and events are displayed correctly.
Related
first post. Trying so solve an issue I am seeing here between my Razor view and model. I have a popup window that is being fed a partial view and model.
public IActionResult ClickedCovid19Question(int id)
{
var existingQ = db.CustomerInfoItems.Find(id);
var suffix = existingQ.Suffix;
if (suffix.Length == 2)
suffix = suffix.Insert(0, "0");
var salesman = SalesmanHelper.GetSalesmanNum();
var par = db.Pars.Where(p => p.AccountNo == existingQ.CustNum).Where(p => p.Suffix == suffix)
.Where(p => p.SalesmanNumber == salesman).FirstOrDefault();
var clickedCovid19Model = new ClickedCovidQuestionModel
{ //insert model data here }
clickedCovid19Model.Machines = db.MachinePopulationItems
.Where(m => m.CustNum == existingQ.CustNum)
.ToList();
return View("~/Views/Covid19/_ClickedCovid19Question.cshtml", clickedCovid19Model);
}
This works great on the first page render. I see the data fill my UI elements that are called from the #model on the razor page. When my user updates a field here and submits, I use this function
function SaveClickedCovid19Question(idJS) {
C19ParChanged('#Model.Par');
var jsonJS = SerializeForm("#c19QuestionForm");
$.ajax({
url: '/Covid19/SaveClickedCovid19Question',
type: 'GET',
data:
{
id: idJS,
json: jsonJS
},
success: function (data) {
Alert(data);
RefreshLV("CovidQuestions");
HideWindow("#Covid19Question");
},
error: function (data, error, e2) {
debugger;
}
});
}
However, after the popup window is closed, and another popup is opened, we call that same ClickedCovid19Question IActionResult to populate our form again. It populates the UI fine with the new model it generated, debugging shows it creates a new model with all the correct data.
The issue arrises when a user submits this form again, the model on the Razor view seems to think it is still the model of the very first submission. An example of this is the first line of the javascript function. When the razor view was created, it had the correct #Model.Par data, as I could see when I created a few elements to display it. However, when trying to capture that data using #Model.Par, it captures the original Model.Par data.
Long story short, subsequent popups don't overwrite the Model data from the very first one. I am stumped, because this system works in so many other areas of our codebase.
I can fix this buy creating hidden elements that will store the data I need to send in any requests, but I feel like there has to be a better answer than that.
Edit: Below is an example I was using to test. The view part below will always display the correct par data in the id=parID input box. However, on the second popup and everytime after, if I was to run the simple javascript function below to find the data held by model, it will ALWAYS update to the data from the first model the page ever rendered, which seems inconsistent with other areas of my code that do work normally.
function updateParID() {
$("#c19QuestionForm").find("#parID").val('#Model.Par');
}
<input id="parID" type="text" disabled="disabled" value="#Model.Par"/>
<partial name="Forms/_FormDropDown" model=#(new FormDropDownModel { Name = "Par", Values = Lists.ParStates(), Value = Model.CallsPerYear}) />
<button type="submit" onclick="RefreshWindow('#Model.ID')">Refresh</button>
<button type="submit" onclick="updateParID()">Update Par ID</button>
That #Model.Par (or whatever prop you have in #Model) renders before anything shows up in browser.
Razor page will render your view and then pass it to browser.
so if you want to fetch data using ajax you should manually put data received from ajax into you html controls.
Have a nice coding day :)
So, I actually ended up solving this. My issue was, trying to bind the data from the #Model.Par or any model data INSIDE a javascript function will ALWAYS bind using the initial model. Every subsequent call to this function will ALWAYS only use that very first model.
My solution that I overlooked was to actually send the data to the function from the model as a parameter first, and not try to bind it inside the javascript function.
Example: My edit has these lines
function updateParID() {
$("#c19QuestionForm").find("#parID").val('#Model.Par');
}
<button type="submit" onclick="updateParID()">Update Par ID</button>
When I change the order of how I capture that model to this:
function updateParID(parID) {
$("#c19QuestionForm").find("#parID").val(parID);
}
<button type="submit" onclick="updateParID('#Model.Par')">Update Par ID</button>
This now correctly captures the model data that is present. I am sure there is some reason javascript works this way, but it is unknown to me, if anyone can shed light on it. Forgive me if it is a simple answer, I am new to web programming. Thank you all for helping out!
I have been searching for a solution this problem for quite some time, including browsing the message board here. To start off, I will refer to an existing post:
I have used the most popular solution, and the controller successfully runs the query:
[HttpGet]
public ActionResult LoadBidders(int Id)
{
List<tblWinLossBidderMap> bidders = _context.tblWinLossBidderMaps.Where(p => p.WinLossID == Id).ToList();
return PartialView("_WinLossBidderView", bidders);
}
The Javascript
$(document).ready(function () {
$("#pY").on("click", function () {
var temp = $("#WinLossID").val();
$.ajax({
url: "/WinLoss/LoadBidders",
type: "GET",
data: { Id: temp }
})
.done(function(partialViewResult) {
$("#BidderCompany").html(partialViewResult);
});
});
});
The problem I have is that when the controller exits, back into the Javascript, I get an exception "Microsoft.CSharp.RuntimeBinder.RuntimeBinderException", "Cannot convert null to 'bool' because it is a non-nullable type value".
Note that the partial view uses a foreach to display the data. Ideally, once this is working, I will take the code snippet and append it after another jquery function that actually adds to this list. The effect is the user would fill in part of a larger form (like master/detail), click a button, a record would be added, and then this routine would update the partial view with the updated information. I doubt this part is important, but just including it for completeness.
Is there some something missing from my code?
Note that I am using Visual Studio 2015.
The application I'm working on is an internal business application for managers. It's a C# web application. The main office has an instance of this app running and it always has the latest version. Each store has it's own instance of the application running as well, but may not always have the latest version. A manager logs in to the main office app and then selects a store to view. That store's instance is pulled up in the main part of the app, the upper menu bar is from the main office's instance. Thus, it is possible that the main office has v1.8 and a store to have v1.7.
There are some features in 1.8 that show up on the menu bar that are not present in 1.7 that I would like to hide. The main page has multiple partials that get loaded and the very last partial has the specific store's version number that is determined by the code on that store's server. Because of this, the only way to get the version number is to get it after it is rendered on the page. The main problem I'm having is that the Javascript I'm using to hide the links to the new features is running before the partial with the version number loads.
I need the Javascript to wait until the entire page finishes loading to execute the hiding code. Also, the application is only run in Chrome.
Here is the code I've got to hide the links:
$(window).load(function () {
if ($('.version').length !== 0) {
if (parseFloat($('.version').text().slice(5)) > 1.7) {
$('.analysis').show();
} else {
$('.analysis').hide();
}
}
});
If you are loading the partial with ajax on the client side explicitly, you can just add a complete function to call:
$( "#storeContainer" ).load( "url/for/partial", function () {
if ($('.version').length !== 0) {
if (parseFloat($('.version').text().slice(5)) > 1.7) {
$('.analysis').show();
} else {
$('.analysis').hide();
}
}
});
Of course, you'll probably want the "url/for/partial" to use #Url.Content or #Url.Action if you can.
If you are using The Ajax Helper, you can set the OnSuccess property of your AjaxOptions to call you back:
#Ajax.ActionLink("Refresh",
"Store",
new AjaxOptions {
HttpMethod = "POST",
UpdateTargetId = "storeContainer",
InsertionMode = InsertionMode.Replace,
OnSuccess = "updateSuccess" });
where you have defined your OnSuccess function in javascript:
var updateSuccess = function () {
if ($('.version').length !== 0) {
if (parseFloat($('.version').text().slice(5)) > 1.7) {
$('.analysis').show();
} else {
$('.analysis').hide();
}
}
There are some other ideas about how to include the script in your partial view or call it during your ajax success event on How to initialize jquery ui widgets that may be loaded dynamically in MVC3 application
If you were using Asp.net AJAX, you could use Sys.Application.add_load(function(){...}).
Have you tried using
$(document).on("ready", function() {
});
in place of $window.load()?
I never use Razor in asp.net MVC so I really don't know how it works.
Every time I want to tag a function in my Controller I use jquery ajax and I write very javascript code and my projects are very messy.
Now I want to make something different.
I have controller named as HomeController where I get data from Sql Server Database, using model entity for that.
public class HomeController : Controller
{
public JsonResult getClasses()
{
IList<Class> classes = (from x in db.Class select x).Distinct().ToList();
return Json(classes, JsonRequestBehavior.AllowGet);
}
public JsonResult getTypes(string className)
{
IList<String> allTypes = (from type in db.Type
where type.class_name == className
orderby type.type_name
select type.type_name).Distinct().ToList();
return Json(allTypes, JsonRequestBehavior.AllowGet);
}
}
And I have master.page (named as SiteMaster) where I get this data through jquery ajax.
<body>
<div id="header">
<ul class="classesName"></ul>
</div>
</body>
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
url: "/Home/getClasses",
type: "GET",
data: {},
success: function (result) {
for (n = 0; n < result.length; n++) {
$('.classesName').append('<li><a href="#" onclick="showTypes( \'' + result[n].class_name + '\')" >' + result[n].class_name + '</a></li>');
}
}
});
</script>
I have another ajax for getting the Types when some Class is clicked..but all this I want to change so I can use #Razor.
All I want is to show the data from getClasses() into the masterPage and when some Class is clicked, to send that argument into getTypes(string className) but without using javascript and use #Razor.
So my question is can I do this and how?
The first part (sending the result of getClasses() to your view) can be done with Razor alone, because all of that work can be done on the server.
It is important to understand that the primary strength of Razor is that it allows you to perform (almost, if not) any C# on your views. So doing what you want can be as simple as writing the code as if you were coding in C#:
#{
// I'd suggest you refactor your code to have your `getClasses()` function
// readily available somewhere that's not a controller
var classes = Data.getClasses();
}
<div id="header">
<ul class="classesName">
#foreach (var clazz in classes) {
<li>
#clazz
</li>
}
</ul>
</div>
For the second part (getting the Types when the link is clicked), you're out of luck. The click has to happen on the client, so by then your C# would have been evaluated, the HTML flushed, and the time for your Razor to run would have come and gone. If those types aren't cached on the page somehow, you'll have to make a request against the server again (and AJAX is one way to do that).
You don't need to use ajax to load the initial master page, just return a view containing all the class data you need to display as that saves you the extra trip to the server. As for getting the data when a class is clicked that is an ideal place to use Ajax and to do that in Razor you would use one of the many #Ajax.xxx helpers (#Ajax.RawActionLink, #Ajax.BeginForm, etc.). The following link might be a good place to start looking at how views are used in asp.net MVC views tutorial
I'm in a bit of a bind here, I am trying to submit a form using ajax, all goes well and dandy until after the server has done it's thing, it decides to load to the action onto a new page, which is exactly what I do not want.
Here is my controller
[HttpPost]
public ActionResult Submit(int id, string trainingProgramId, FormCollection form, User user)
{
//Do Some action
return null;
}
In a different controller I have it set up to do $return PartialView(model);
this is the JQuery code that I am using.
$(function () {
$("form").submit(function (e) {
if (nextquestion()) { //check if posting can proceed
$.ajax({
type: "POST",
data: $(this).serialize(),
url: $(this).attr("action"),
success: function (response) {
alert(response);
$('#cases:last-child').insertAfter(response);
},
error: function (data) { }
});
}
e.preventDefault();
});
});
In all cases I am being redirected to a different url after performing the operation. Which is not the intention, especially if my intention might be to load more stuff into the page.
I've been tring everything, a bunch of solutions, but once my controller does a return statement the page automatically reloads to $/Submit
I have added $ #Scripts.Render("https://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.min.js"); to my scripts
From any other example I am finding this should work as I want it to, by remaining on the same page, however I am finding it difficult to understand who is responsible for changing the page either way. When I return my PartialView, a completely new page loads with the model as I've had it set up for the Partial View to be inserted originally.
Anyone care to explain what is going on or why my code is wrong?
I can't find it after a whole day of trying to debug.