I am new to MVC and trying to use DotNet High Chart for the first time. I am following this tutorial in Visual Studios MVC 5.
My Bundles :
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
bundles.Add(new Bundle("~/bundles/highchart").Include(
"~/Scripts/Highcharts-4.0.1/js/highchart.js"));
}
}
}
My Model:
namespace Charts2.Models
{
public class TransactionCount
{
public string MonthName { get; set; }
public int Count { get; set; }
}
}
My Controller :
namespace Charts2.Controllers
{
public class ChartSampleController : Controller
{
// GET: ChartSample
public ActionResult Index()
{
//create a collection of data
var transactionCounts = new List<TransactionCount>{
new TransactionCount(){ MonthName="January", Count=30},
new TransactionCount(){ MonthName="Febuary", Count=40},
new TransactionCount(){ MonthName="March", Count=4},
new TransactionCount(){ MonthName="April", Count=35},
};
// modify data type to make it of array types
var xDataMonths = transactionCounts.Select(i => i.MonthName).ToArray();
var yDataCounts = transactionCounts.Select(i => new object[] { i.Count }).ToArray();
//instanciate an object of the high charts type
var chart = new Highcharts("chart")
// define the type of chart
.InitChart(new Chart { DefaultSeriesType = ChartTypes.Line})
//overall title of the chart
.SetTitle(new Title { Text = "Incoming Transactions per hour"})
//small label below the main title
.SetSubtitle(new Subtitle { Text = "Accounting"})
// load the x values
.SetXAxis(new XAxis {Categories = xDataMonths})
// set the y title
.SetYAxis(new YAxis { Title = new YAxisTitle { Text = "Number of Transactions"}})
.SetTooltip(new Tooltip{
Enabled = true,
Formatter = #"function() { return '<b>'+this.series.name +'</b><br/>'+this.x+': '+this.y;}"
})
.SetPlotOptions(new PlotOptions{
Line = new PlotOptionsLine {
DataLabels = new PlotOptionsLineDataLabels {
Enabled = true
},
EnableMouseTracking = false
}
})
//load y values
.SetSeries(new []
{
new Series {Name = "Hour", Data = new Data(yDataCounts)},
});
return View(chart);
}
}
}
and my view:
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#model DotNet.Highcharts.Highcharts
<p> My Chart </p>
#(Model)
My shared _Index:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/highchart")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
#Html.Partial("_LoginPartial")
</div>
</div>
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
Whenever I run the application the chart does not generate at all. I had followed the tutorial and cannot understand where I am going wrong. On the console I am getting the following exception:
Uncaught ReferenceError: Highcharts is not defined
Any advice would be greatly appreciated
Thanks
Can you please post entire view code. As in your current view you are not adding high chart bundle to view
Some thing like
#Scripts.Render("~/bundles/highchart")
I've realised where I was going wrong. I was missing an s at the end of the bundle name, I changed the bundle:
bundles.Add(new ScriptBundle("~/bundles/highcharts").Include(
"~/Scripts/Highcharts-4.0.1/js/highcharts.js"
));
and updated the _index according and now it works.
Related
I'm trying to draw a chart using google chart tools. I'd like to know if there is a way to take the array values from my backing bean using Javascript. I have the following code but, when I test it, it looks like it doesn't get the backing bean:
my xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<ui:composition template="/pages/menu.xhtml">
<ui:define name="conteudo">
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
// Load the Visualization API and the corechart package.
google.charts.load('current'); // Don't need to specify chart libraries!
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawVisualization);
function drawVisualization() {
var wrapper = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
dataTable: ["#{chartBean.countries}", "#{chartBean.numbers}"],
options: {'title': 'Countries'},
containerId: 'vis_div'
});
wrapper.draw();
}
</script>
<div id="vis_div" style="width: 600px; height: 400px;"></div>
</ui:define>
</ui:composition>
</html>
my backing bean:
#ManagedBean
#RequestScoped
public class ChartBeean {
private String[] countries = {"","Germany","USA","Brazil","Canada","France","Russia"};
private int[] numbers = {0,700,300,400,500,600,800};
public String[] getCountries() {
return countries;
}
public void setCountries(String[] countries) {
this.countries = countries;
}
public int[] getNumbers() {
return numbers;
}
public void setNumbers(int[] numbers) {
this.numbers = numbers;
}
}
Can anyone help me with this?
PS:I know there is a specific api to use google charts in primefaces, but I would like to use the pure google chart api.
for your query regarding "..it looks like it doesn't get the backing bean"
Your are using #{chartBean.countries} and your Managed Bean name is ChartBeean.
You need to use #{chartBeean.countries} and "#{chartBeean.numbers}"
Working Code for Charts -
You do not need the " " on
dataTable : [ #{chartBeean.countriesString}, #{chartBeean.numbersString} ])
I have added ' in the String for countries.
XHTML
<h:head>
<title>Charts Test</title>
<!--Load the AJAX API-->
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
// Load the Visualization API and the corechart package.
google.charts.load('current'); // Don't need to specify chart libraries!
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawVisualization);
function drawVisualization() {
var wrapper = new google.visualization.ChartWrapper(
{
chartType : 'ColumnChart',
dataTable : [ #{chartBeean.countriesString},
#{chartBeean.numbersString} ],
options : {
'title' : 'Countries'
},
containerId : 'chart_div'
});
wrapper.draw();
}
</script>
</h:head>
<h:body>
<!--Div that will hold the pie chart-->
<div id="chart_div"></div>
</h:body>
</html>
ManagedBean
package com;
import java.util.Arrays;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean
#RequestScoped
public class ChartBeean {
private String[] countries = { "'Germany'", "'USA'", "'Brazil'", "'Canada'", "'France'", "'Russia'" };
private String[] numbers = { "700", "300", "400", "500", "600", "800" };
public ChartBeean() {
super();
System.out.println("ChartBeean..");
}
#PostConstruct
public void init() {
System.out.println("ChartBeean init..");
}
public String getCountriesString() {
// ['Germany', 'USA', 'Brazil', 'Canada', 'France', 'Russia']
String deepToString = Arrays.deepToString(countries);
System.out.println(deepToString);
return deepToString;
}
public String getNumbersString() {
// [700, 300, 400, 500, 600, 800]
String deepToString = Arrays.deepToString(numbers);
System.out.println(deepToString);
return deepToString;
}
}
I try use plugin from
https://bunjeeb.com/2014/06/03/mvc-tooltip-validation-using-jquery-and-bootstrap/
But Validation Error appeared under EditControl first time and once disappeared when I push the button "Save" and then like a tooltip when when I push the button "Save" second time
Please help me
Thanks a lot
1. _Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - Moving Pro Services</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
<link href="#Url.Content("~/Content/jquery.validate.mvc.css")" rel="stylesheet" type="text/css"/>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
#if (HttpContext.Current.User.Identity.IsAuthenticated)
{
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Moving Pro Services", "Index", "Home", new {area = ""}, new {#class = "navbar-brand"})
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
Services <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li>#Html.ActionLink("Companies", "Index", "Companies")</li>
<li>#Html.ActionLink("App Versions", "Index", "AppVersions")</li>
#if (User.Identity.IsAuthenticated)
{
if (User.IsInRole("Administrator"))
{
<li>#Html.ActionLink("Create User", "Register", "Account")</li>
}
}
</ul>
</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
#Html.Partial("_LoginPartial")
</div>
</div>
}
</div>
<div class="container body-content">
#RenderBody()
<hr/>
<footer>
<p>© #DateTime.Now.Year - Moving Pro Services</p>
</footer>
</div>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
<div id='myModal' class='modal fade in'>
<div class="modal-dialog">
<div class="modal-content">
<div id='myModalContent'></div>
</div>
</div>
</div>
</body>
</html>
2. View
#model Maintenance.Models.AppVersion
#using (Html.BeginForm())
{
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Edit App Version</h4>
</div>
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.AppVersion1)
<div class="modal-body">
<div class="form-horizontal">
<div class="form-group margin-bottom">
#Html.LabelFor(model => model.AppVersionDescription, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.AppVersionDescription, new { htmlAttributes = new { #class = "form-control", autofocus = "" } })
#Html.ValidationMessageFor(model => model.AppVersionDescription)
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input class="btn btn-primary" type="submit" value="Save changes" id="approve-btn" />
<button class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script>
$(function () {
$("form input").tooltipValidation({
placement: "right"
});
});
</script>
}
3. Script for create dialog for Edit
$(function () {
$.ajaxSetup({ cache: false });
$(document).on("click", ".modal-link", function (e) {
$('#myModalContent').load(this.href, function () {
$('#myModal').modal
(
{
keyboard: true
}, 'show'
);
bindForm(this);
});
return false;
});
$(document).on("click", "a[data-modal]", function (e)
{
$('#myModalContent').load(this.href, function ()
{
$('#myModal').modal
(
{
keyboard: true
}, 'show'
);
bindForm(this);
});
return false;
});
$(window.document).on('shown.bs.modal', '.modal', function () {
window.setTimeout(function () {
$('[autofocus]', this).focus();
}.bind(this), 100);
});
});
function bindForm(dialog) {
$('form', dialog).submit(function () {
var isValid = true; // assume all OK
$('form').validate(); // perform validation on the form
$('input[type="text"]').each(function (index, item) { // could change selector to suit e.g $('input, textarea').each(..
if (!$(this).valid()) {
isValid = false; // signal errors
return false; // break out of loop
}
});
if (!isValid) {
return false; // exit
}
$('#progress').show();
$.ajax({
url: this.action,
modal: true,
draggable: true,
resizable: false,
type: this.method,
data: $(this).serialize(),
success: function (result) {
$('#myModal').modal('hide');
$('#progress').hide();
//location.reload();
alert(result.message);
}
});
return false;
});
}
4. Model
namespace Maintenance.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public partial class AppVersion
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public AppVersion()
{
this.Companies = new HashSet<Company>();
}
[StringLength(40)]
[Display(Name = "App Version")]
public string AppVersion1 { get; set; }
[StringLength(40)]
[Display(Name = "App Version Description")]
public string AppVersionDescription { get; set; }
[ReadOnly(true)]
[Display(Name = "Creating Date")]
public System.DateTime CreateDate { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Company> Companies { get; set; }
}
}
5. Plugin to show tooltip
/*
* Project: MVC Validation Framework
* Description: This plugin will convert client side validation elements to bootstrap tooltips
* Author: Ahmad Aqrabawi, Mohamed Aljaber
* License: MIT
*/
// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
; (function ($, window, document, undefined) {
// undefined is used here as the undefined global variable in ECMAScript 3 is
// mutable (ie. it can be changed by someone else). undefined isn't really being
// passed in so we can ensure the value of it is truly undefined. In ES5, undefined
// can no longer be modified.
// window and document are passed through as local variable rather than global
// as this (slightly) quickens the resolution process and can be more efficiently
// minified (especially when both are regularly referenced in your plugin).
// Create the defaults once
var pluginName = "tooltipValidation";
var defaults = {
};
// The actual plugin constructor
function Plugin(element, options) {
this.element = element;
// jQuery has an extend method which merges the contents of two or
// more objects, storing the result in the first object. The first object
// is generally empty as we don't want to alter the default options for
// future instances of the plugin
this.options = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype = {
init: function () {
// Place initialization logic here
// You already have access to the DOM element and
// the options via the instance, e.g. this.element
// and this.options
// you can add more functions like the one below and
// call them like so: this.yourOtherFunction(this.element, this.options).
var elem = $(this.element),
name = elem.attr("name"),
defaultBorderCss = elem.css('border'),
tooltipPlacement = this.options.placement;
if (name) {
var errValElem = $('span[data-valmsg-for="' + name + '"]');
errValElem.hide();
function onDOMSubtreeModified(errValElem) {
errValElem.bind("DOMSubtreeModified", function () {
elem.tooltip("destroy");
elem.siblings("div.tooltip").remove();
var isTooltipPluginAttached = elem.data("plugin_tooltipValidation");
if (!isTooltipPluginAttached) {
elem.tooltip({
'title': errValElem.text(),
'animation': 'true',
'placement': tooltipPlacement || 'top',
'trigger': 'focus'
});
}
if (errValElem.hasClass("field-validation-error")) {
elem.css('border', '1px solid red');
}
else {
elem.css('border', defaultBorderCss);
elem.tooltip('destroy');
elem.siblings("div.tooltip").remove();
}
});
};
function showTooltipOfError(event) {
var inputField = event.currentTarget;
if (errValElem.hasClass("field-validation-error") || errValElem.hasClass("field-error")) {
$(inputField).siblings("div.tooltip").remove();
$(inputField).tooltip({
'title': $(errValElem).text(),
'animation': 'true',
'placement': tooltipPlacement || 'top',
'trigger': 'focus'
});
$(inputField).tooltip('show')
$(".tooltip").addClass("error");
}
};
if (elem.is('select')) { //Handle tooltip on input type = select (DropdownList)
elem.on("focus mouseenter", function (event) {
showTooltipOfError(event);
});
elem.on("mouseleave", function (event) {
var inputField = event.currentTarget;
$(inputField).tooltip('hide');
});
onDOMSubtreeModified(errValElem);
}
else if (elem.attr('type') == 'date') { //Handle if input type = date
elem.on("focus mouseenter", function (event) {
showTooltipOfError(event);
});
elem.on("mouseleave", function (event) {
var inputField = event.currentTarget;
$(inputField).tooltip('hide');
});
elem.on("change", function (event) {
var inputField = event.currentTarget;
if ($(inputField).val() != "") {
elem.css('border', defaultBorderCss);
elem.tooltip('destroy');
elem.siblings("div.tooltip").remove();
}
else
elem.css('border', '1px solid red');
});
onDOMSubtreeModified(errValElem);
}
else if (elem.attr('type') == 'file') {
elem.on("focus mouseenter", function (event) {
showTooltipOfError(event);
});
elem.on("mouseleave", function (event) {
var inputField = event.currentTarget;
$(inputField).tooltip('hide');
});
onDOMSubtreeModified(errValElem);
}
else {
elem.on("focus", function (event) {
showTooltipOfError(event);
});
onDOMSubtreeModified(errValElem);
}
}
}
};
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[pluginName] = function (options) {
return this.each(function () {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName, new Plugin(this, options));
}
});
};
})(jQuery, window, document);
I tried to minimize huge problem to a small one so I created the new sample web project; mvc-empty in VS. I created one view named „Index” in Home controller. Index view code:
#model WebApplication16.ViewModels.Home.IndexVM
#{
ViewBag.Title = "Index";
}
#Html.Partial("~/Views/Home/_Orders.cshtml", Model.Orders)
#section scripts{
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script>
$("#Type").change(function () {
$('#order-current > img').remove();
var currentOrder = "#Type_" + $("#Type").find('option:selected').text();
var $img = $(currentOrder).clone();
$img.removeClass("hidden");
$("#order-current").append($img);
$("#ajax-form").submit();
});
</script>
}
Home controller code:
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
IndexVM dataVM = new IndexVM();
GetControlsDataSource(dataVM.Orders);
return View(dataVM);
}
private static void GetControlsDataSource(OrdersVM dataVM)
{
List<SelectListItem> typeControlDataSource = new List<SelectListItem>();
foreach (var en in Enum.GetValues(typeof(TypeEnum)))
{
SelectListItem item = new SelectListItem();
item.Text = en.ToString();
item.Value = ((int)en).ToString();
typeControlDataSource.Add(item);
}
dataVM.TypeControlDataSource = typeControlDataSource;
}
[HttpPost]
public ActionResult Pay(IndexVM dataVM)
{
GetControlsDataSource(dataVM.Orders);
if (ModelState.IsValid)
{
dataVM.Orders.Info = "Info bla bla bla";
return PartialView("~/Views/Home/_Orders.cshtml", dataVM.Orders);
}
else
{
return View(dataVM);
}
}
}
There is also a partial view named “_Orders”, which is rendered on the Index view.The code of _Orders partial view:
#model WebApplication16.ViewModels.Home.OrdersVM
#using (Ajax.BeginForm("Pay", "Home", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "result",
}, new { id = "ajax-form" }))
{
<div id="result">
<div id="order-current">
</div>
<div>
#Html.TextBoxFor(x => x.Name, new { #class = "form-control", style = "margin-top:10px;", id = "Name" })
#Html.ValidationMessageFor(x => x.Name)
</div>
<div>
#Html.DropDownListFor(x => x.Type, Model.TypeControlDataSource, new { #class = "form-control", style = "margin-top:10px;", id = "Type", })
#Html.ValidationMessageFor(x => x.Type)
</div>
<div>
<p>#Model.Info</p>
</div>
<button type="submit" class="btn btn-primary" name="ok"> OK</button>
</div>
}
<div id="orders-container">
<img id="Type_I" src="~/App_Images/Type_I.png" class="img-responsive hidden" />
<img id="Type_II" src="~/App_Images/Type_II.png" class="img-responsive hidden" />
<img id="Type_III" src="~/App_Images/Type_III.png" class="img-responsive hidden"/>
</div>
Index model is described by class IndexVM:
public class IndexVM
{
public IndexVM()
{
this.Orders = new OrdersVM();
}
public OrdersVM Orders { get; set; }
}
_Orders model is described by class OrdersVM:
public class OrdersVM
{
[Required]
public string Name { get; set; }
public string Info { get; set; }
[Required]
public TypeEnum Type { get; set; }
public List<SelectListItem> TypeControlDataSource { get; set; }
}
public enum TypeEnum
{
I,
II,
III
}
After change of value in DropDownListFor control with id=”Type”, the picture from hidden field should be injected by jquery code located in Index view into container with id=”order-current” and after that operation the ajax-form should be submitted. It works properly but after calling
return PartialView("~/Views/Home/_Orders.cshtml", dataVM.Orders);
from the HomeController, the field Info is updated properly but the injected picture from the “order-current” div container is gone. I tried to see what’s wrong in Google Chrome using F12 button and there are no errors but appeared an infinite loop in “browserLink” script. I can’t explain why.
All I want is to see the injected picture in container with id=”order-current after submitting the ajax-form. How to do this and what I did wrong?
Thanks to my friend I finally solved the problem. After updating the “result” container, all events added by jQuery to controls located in this container are unpinned. That’s why it crashes.
The way to make it work correctly is to create a function and pin it to the event OnComplete of AjaxBeginForm. After each update of the result container via ajax, this function is called. I also made a small mistake in Home controller because I inserted a wrong view model class. After all changes, it looks like this;
Home controller code:
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
IndexVM dataVM = new IndexVM();
GetControlsDataSource(dataVM.Orders);
return View(dataVM);
}
private static void GetControlsDataSource(OrdersVM dataVM)
{
List<SelectListItem> typeControlDataSource = new List<SelectListItem>();
foreach (var en in Enum.GetValues(typeof(TypeEnum)))
{
SelectListItem item = new SelectListItem();
item.Text = en.ToString();
item.Value = ((int)en).ToString();
typeControlDataSource.Add(item);
}
dataVM.TypeControlDataSource = typeControlDataSource;
}
[HttpPost]
public ActionResult Pay(OrdersVM dataVM)
{
GetControlsDataSource(dataVM);
if (ModelState.IsValid)
{
dataVM.Info = "Info bla bla bla";
return PartialView("~/Views/Home/_Orders.cshtml", dataVM);
}
else
{
return View(dataVM);
}
}
}
Index view:
#model WebApplication16.ViewModels.Home.IndexVM
#{
ViewBag.Title = "Index";
}
#Html.Partial("~/Views/Home/_Orders.cshtml", Model.Orders)
<div id="orders-container">
<img id="Type_I" src="~/App_Images/Type_I.png" class="img-responsive hidden" />
<img id="Type_II" src="~/App_Images/Type_II.png" class="img-responsive hidden" />
<img id="Type_III" src="~/App_Images/Type_III.png" class="img-responsive hidden" />
</div>
#section scripts{
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script>
function imageOnChangeEvent() {
$("#ajax-form").submit();
}
function OnCompleteAjaxForm() {
$('#order-current > img').remove();
var currentOrder = "#Type_" + $("#Type").find('option:selected').text();
var $img = $(currentOrder).clone();
$img.removeClass("hidden");
$("#order-current").append($img);
}
</script>
}
_Orders partial view code:
#model WebApplication16.ViewModels.Home.OrdersVM
<div id="result">
#using (Ajax.BeginForm("Pay", "Home", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "result",
OnComplete = "OnCompleteAjaxForm()"
}, new { id = "ajax-form" }))
{
<div id="order-current">
</div>
<div>
#Html.TextBoxFor(x => x.Name, new { #class = "form-control", style = "margin-top:10px;", id = "Name" })
#Html.ValidationMessageFor(x => x.Name)
</div>
<div>
#Html.DropDownListFor(x => x.Type, Model.TypeControlDataSource, new { #class = "form-control", style = "margin-top:10px;", id = "Type", onchange = "imageOnChangeEvent()" })
#Html.ValidationMessageFor(x => x.Type)
</div>
<div>
<p>#Model.Info</p>
</div>
<button type="submit" class="btn btn-primary" id="button_ok" name="ok"> OK</button>
}
</div>
I've been able to get FullCalendar to load in my webpage but I can't seem to successfully pass my test JSON data to the calendar and have it render events. I'm not sure what I'm doing wrong.
I'm following this website's example and I even downloaded their source code and was able to run it successfully in my dev environment. My code seems to almost completely mirror their's yet I still can't render events. I even went back and added javascript files to my bundles just in case that was the issue but to no success.
Any ideas?
Bundles:
public class BundleConfig
{
// For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css",
"~/Content/themes/base/jquery.ui.all.css",
"~/Content/fullcalendar.css"));
/*Kendo UI Instructions that were followed
* http://docs.telerik.com/kendo-ui/aspnet-mvc/asp-net-mvc-5
*/
bundles.Add(new ScriptBundle("~/bundles/kendo").Include(
"~/Scripts/kendo/2016.2.714/kendo.webcomponents.min.js",
// "~/Scripts/kendo/kendo.timezones.min.js", // uncomment if using the Scheduler
"~/Scripts/kendo/2016.2.714/kendo.aspnetmvc.min.js",
"~/Scripts/kendo/2016.2.714/jquery.min.js",
"~/Scripts/kendo/2016.2.714/kendo.ui.core.min.js",
"~/Scripts/kendo/2016.2.714/kendo.calendar.min.js",
"~/Scripts/kendo/2016.2.714/kendo.popup.min.js",
"~/Scripts/kendo/2016.2.714/kendo.datepicker.min.js"));
bundles.Add(new StyleBundle("~/Content/kendo/css").Include(
"~/Content/kendo/2016.2.714/kendo.common-bootstrap.min.css",
"~/Content/kendo/2016.2.714/kendo.bootstrap.min.css",
"~/Content/kendo/2016.2.714/kendo.common.min.css",
"~/Content/kendo/2016.2.714/kendo.defualt.min.css"));
bundles.Add(new ScriptBundle("~/bundles/fullcalendar").Include(
"~/Scripts/jquery-ui-1.12.0.min.js",
"~/Scripts/moment.min.js",
"~/Scripts/fullcalendar.min.js"));
bundles.IgnoreList.Clear();
}
_Layout:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Time Zone Event Calendar</title>
#Styles.Render("~/Content/kendo/css")
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/kendo")
#Scripts.Render("~/bundles/fullcalendar")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Time Zone Event Calendar", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - Time Zone Event Calendar</p>
</footer>
</div>
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
</body>
</html>
Index:
#{
ViewBag.Title = "Home Page";
}
<head>
#section scripts{
<script type="text/javascript">
$(document).ready(function ()
{
$('#calendar').fullCalendar(
{
header:
{
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: false,
events: "/home/loadevents/"
})
});
</script>
<script type="text/javascript">
$(document).ready(function () {
$("#pickDateTime").kendoDateTimePicker({
culture: "es-Es",
interval: 1,
format: "yyyy/MM/dd hh:mm tt",
parseFormats: ["MMMM yyyy", "HH:mm"]
});
});
</script>
}
</head>
<body>
<div id="headerBar">
<div id="datepicker">
<form method="post">
<input id="pickDateTime" name="DateTimePicker" />
<input type="submit" value="Add" />
</form>
</div>
</div>
<div id="calendar"></div>
</body>
HomeController:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
public ActionResult LoadEvents (double start, double end)
{
var fromDate = ConvertFromUnixTimestamp(start);
var toDate = ConvertFromUnixTimestamp(end);
var eventList = GetEvents();
var rows = eventList.ToArray();
return Json(rows, JsonRequestBehavior.AllowGet);
}
private List<CalendarEventsViewModel> GetEvents()
{
List<CalendarEventsViewModel> eventList = new List<CalendarEventsViewModel>();
CalendarEventsViewModel newEvent = new CalendarEventsViewModel
{
ID = "1",
EventName = "Event 1",
StartDateString = DateTime.Now.AddDays(1).ToString("s"),
EndDateString = DateTime.Now.AddDays(1).ToString("s"),
AllDay = false
};
eventList.Add(newEvent);
newEvent = new CalendarEventsViewModel
{
ID = "1",
EventName = "Event 3",
StartDateString = DateTime.Now.AddDays(2).ToString("s"),
EndDateString = DateTime.Now.AddDays(3).ToString("s"),
AllDay = false
};
eventList.Add(newEvent);
return eventList;
}
private static DateTime ConvertFromUnixTimestamp(double timestamp)
{
var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
return origin.AddSeconds(timestamp);
}
}
CalendarEventsViewModel:
public class CalendarEventsViewModel
{
public string ID { get; set; }
public string EventName { get; set; }
public string EventText { get; set; }
public string StartDateString { get; set; }
public string EndDateString { get; set; }
public bool AllDay { get; set; }
}
I think you have made the same mistake I did when I first set it up, the example you are looking at only works for version one of FullCalendar. In version two it's not a unix timestamp your LoadEvents action receives.
It's a moment object that is passed to the action, if you remove your ConvertFromUnixTimestamp method and change your start and end parameters from double to DateTime I think it will start working.
If you break point your LoadEvents action without making any changes I am pretty confident it's not even being called.
Your property names should match those of the event object otherwise it will treat them like non standard fields.
I am trying to use the JQuery UI date picker but it only displays as a normal textbox. When I open the Google Chrome debugger there is one error "Uncaught TypeError: $(...).datepicker is not a function"
This is my Bundle.config file
using System.Web;
using System.Web.Optimization;
namespace ultimateorganiser
{
public class BundleConfig
{
// For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery - ui.min.js",
"~/Scripts/Scripts/jquery-ui.js",
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
//JQuery bxSlider
bundles.Add(new ScriptBundle("~/bundles/slider").Include(
"~/Scripts/jquery.bxslider.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/jquery - ui.css",
"~/Content/site.css"));
}
}
}
This is my view with the script code at the bottom
#model ultimateorganiser.Models.ClubMember
#{
ViewBag.Title = "Register";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
//UserDob
<div class="form-group">
#Html.LabelFor(model => model.UserDoB, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UserDoB, new { id = "userdob" })
#Html.ValidationMessageFor(model => model.UserDoB, "", new { #class = "text-danger" })
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function () {
$("#news_date").datepicker({ dateFormat: 'dd/mm/yy' });
});
</script>
}
I think you need to add #Scripts.Render("~/bundles/jquery") in your view.