changing rally basic dropdown menus after display - drop-down-menu

I have a rally.sdk.ui.basic.Dropdown menu in a Rally App that I would like to change based on user input. So I will call display() on the dropdown menu, and then later I want to change the contents of that menu.
Has anybody done this? When I try, it crashes. I've also tried calling destroy() on the dropdown menu and then calling display() on a new menu that I allocate, but that crashes as well with an obscure dojo error.
Any suggestions on how to change dropdown menus on the fly?
I've included a very stripped down example below of trying to destroy and then re-display the menu:
<html>
<head>
<title>Incoming Defects by Severity</title>
<meta http-equiv="X-UA-Compatible" content="IE=7" >
<meta name="Name" content="Defects by Severity" />
<script type="text/javascript" src="https://rally1.rallydev.com/apps/1.29/sdk.js"></script>
<script type="text/javascript">
function DefectChart() {
this.display = function() {
var defectVersionDropdown;
var count = 1;
function makeDefectChart(results){
initDefectVersionDropdown();
};
function renderPage() {
var queryConfig = [];
var startDate = '2011-06-06';
var endDate = '2012-02-02';
var queryArray = ['CreatedDate >= "' + startDate + '"', 'CreatedDate <= "' + endDate + '"'];
var versionFilter = defectVersionDropdown ? defectVersionDropdown.getDisplayedValue() : 'ALL';
if (versionFilter != 'ALL') {
queryArray.push('FoundInBuild contains "' + versionFilter + '"');
}
// console.log(queryArray);
queryConfig.push({
type : 'Defects',
key : 'defects',
query: rally.sdk.util.Query.and(queryArray),
fetch: 'Severity,State,LastUpdateDate,CreationDate,OpenedDate,AcceptedDate,LastUpdateDate,ClosedDate,Environment,FoundInBuild'
});
rallyDataSource.findAll(queryConfig, makeDefectChart);
}
function defectVersionChange(sender, eventArgs) {
var version = eventArgs.value;
renderPage();
}
function initDefectVersionDropdown() {
if (defectVersionDropdown != null) {
defectVersionDropdown.destroy();
defectVersionDropdown = null;
}
if (defectVersionDropdown == null) {
console.log('initDefectVersionDropdown');
count++;
var menuItems = [{label: "ALL", value: "ALL"}];
for (var i=0; i < count; i++) {
menuItems.push({label: count, value: count});
}
var config = {
label: "Found In Version:",
items: menuItems
};
defectVersionDropdown = new rally.sdk.ui.basic.Dropdown(config);
defectVersionDropdown.addEventListener("onChange", defectVersionChange);
defectVersionDropdown.display("defectVersionDiv");
}
}
var workspaceOid = '__WORKSPACE_OID__'; if (workspaceOid.toString().match(/__/)) { workspaceOid = XXX; }
var projectOid = '__PROJECT_OID__'; if (projectOid.toString().match(/__/)) { projectOid = XXX; }
rallyDataSource = new rally.sdk.data.RallyDataSource( workspaceOid,
projectOid,
'__PROJECT_SCOPING_UP__',
'__PROJECT_SCOPING_DOWN__');
initDefectVersionDropdown();
renderPage();
}
}
function getDataAndShow() {
var defectChart = new DefectChart();
defectChart.display();
}
function loadRally() {
rally.addOnLoad(getDataAndShow);
}
loadRally();
</script>
</head>
<body>
<div id="defectVersionDiv"></div>
</body>
</html>

Destroying the old one creating and displaying a new one is the correct way to do this. This is a common pattern when developing apps using the App SDK. If you provide a code snipped along with the dojo error you are getting the community can probably be of better assistance.

Related

Call Ajax.ActionLink using Razor syntax on value changed event

I have a View in which i have criteria a Supplier TextBox a LastMonth dropdown and a Months Textbox.
#using JouleBrokerDB.ViewModels;
#model AssignPayReportToDepositViewModel
#{
ViewBag.Title = "View";
}
<link href="#Url.Content("~/Content/kendo/kendo.common-bootstrap.min.css")" rel="stylesheet" />
<link href="#Url.Content("~/Content/kendo/kendo.bootstrap.min.css")" rel="stylesheet" />
<link href="#Url.Content("~/Content/kendo/kendo.dataviz.min.css")" rel="stylesheet" />
<link href="#Url.Content("~/Content/kendo/kendo.dataviz.bootstrap.min.css")" rel="stylesheet" />
<style>
.treediv {
display: inline-block;
vertical-align: top;
width: 440px;
/*height:400px;*/
min-height: 400px;
text-align: left;
margin: 0 2em;
border-radius: 25px;
border: 2px solid #8AC007;
padding: 15px;
overflow: auto;
}
</style>
<div class="row">
<div class="col-md-9 col-md-offset-1">
#using (Html.BeginForm("Show", "AssignPayReportToDeposit", FormMethod.Post, new { id = "AssignToPayReportForm", #class = "form-horizontal" }))
{
<fieldset>
<!-- Form Name -->
<legend>Assign Pay Report to Deposit</legend>
<div class="form-group">
<!-- Supplier -->
<div class="col-sm-4">
#Html.Label("", "Supplier:", new { #class = "control-label", #for = "textinput" })
<div id="suppliers">
#Html.DropDownListFor(x => x.SuppliersList, new SelectList(Model.SuppliersList, "SupplierID", "Name"), new { id = "ddSupplier", #class = "form-control" })
</div>
</div>
<!-- Last Month -->
<div class="col-sm-4">
#Html.Label("", "Last Month:", new { #class = "control-label", #for = "textinput" })
#Html.DropDownListFor(x => x.LastMonthsList, new SelectList(Model.LastMonthsList), new { #id = "ddLastMonth", #class = "form-control" })
</div>
<!-- Months-->
<div class="col-sm-4">
#Html.Label("", "Months:", new { #class = "control-label", #for = "textinput" })
#Html.TextBox("txtMonths", null, new { type = "number", step = 1, min = 1, max = 12, #class = "form-control", required = "required" })
</div>
</div>
</fieldset>
<div class="treediv">
#Html.Label("", "UnAssigned PayReport:", new { #class = "control-label", #for = "textinput" })
<div id="TreeView_UPR" style="padding:5px"></div>
</div>
<div class="treediv">
#Html.Label("", "Deposits:", new { #class = "control-label", #for = "textinput" })
<h4></h4>
<div id="TreeView_AD" style="padding:5px"></div>
</div>
}
</div>
</div>
<script src="#Url.Content("~/Scripts/kendo/kendo.all.min.js")"></script>
<script src="#Url.Content("~/Scripts/Views/AssignPayReportToDeposit/Show.js")"></script>
Here on this text box i have attached changed event though jQuery. The requirement is that whenever the criteria changes the treeview div will be filled with data will be refreshed.
AssignPayReportsToDeposit.AttachEvents = function () {
$("#ddSupplier").change(AssignPayReportsToDeposit.OnSupplierChange);
$("#ddLastMonth").change(AssignPayReportsToDeposit.OnLastMonthChange);
$("#txtMonths").change(AssignPayReportsToDeposit.OnMonthsChange);
}
these changed event handler will handle the refreshing the treeview. The whole thing is handled through ajax calls.
Now i know that using Ajax.ActionLink and UpdateTargetId parameter with Replace option i can return the treeview in partial view so the manual handling can be removed. but that will require me put the anchor button which user have to click. Requirement is that the refresh of treeview should be done on any criteria change.
Is there any way i am able to achieve this using Ajax.ActionLink (or any another razor syntax that will take load off from the manual handling ) ? On change event of the controls i would like to call a controller using ajax.actionlink which will return a partialview and update the div.
Edit: I am handling this through jQuery right now. so i will post the complete code for more understanding.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using JouleBrokerDB;
using JouleBrokerDB.ViewModels;
using JouleBroker.Filters;
namespace JouleBroker.Controllers
{
[RoutePrefix("AssignPayReportToDeposit")]
[Route("{action=Show}")]
public class AssignPayReportToDepositController : Controller
{
// GET: AssignPayReportToDeposit
//[Route("Show",Name = "APTDShow")]
//[ValidateLogin]
public ActionResult Show()
{
List<SupplierViewModel> suppliers = DBCommon.GetAllSuppliers(false);
SuppliersList_LastMonthsList_ViewModel model = new SuppliersList_LastMonthsList_ViewModel()
{
SuppliersList = suppliers,
LastMonthsList = new List<string>()
};
return View(model);
}
[HttpPost]
[Route("GetUnAssignedPayReports")]
public JsonResult GetUnAssignedPayReports(int SupplierID,
string MonthPaid,
int Months)
{
var payreports = AssignPayReportsToDepositData.GetUnAssignedPayReports(SupplierID,
MonthPaid,
Months);
return Json(payreports);
}
[HttpPost]
[Route("GetAssignedPayReports")]
public JsonResult GetAssignedPayReports(int SupplierID,
string MonthPaid,
int Months)
{
var payreports = AssignPayReportsToDepositData.GetAssignedPayReports(SupplierID,
MonthPaid,
Months);
return Json(payreports);
}
[HttpPost]
[Route("AssignDepositIdToPayReport")]
public bool AssignDepositIdToPayReport(int PayReportID, int DepositID)
{
return AssignPayReportsToDepositData.AssignDepositIdToPayReport(PayReportID, DepositID);
}
}
}
JavaScript File (the code is a bit lengthy so you don't need to look at all of them you can see the methods which are calling the action methods. GetUnAssignedPayReports and GetAssignedPayReports which returns the data which is used to fill the tree view.) I just want this portion to moved to partial view and passing model to partial view generate treeview there and replace the div each time on change event with rendering partial view again. Hope i am clear enough. so change the above methods to return partial instead of json result that what i am trying to achive
function AssignPayReportsToDeposit() { }
AssignPayReportsToDeposit.SelectedSupplierID = 0;
AssignPayReportsToDeposit.SelectedLastMonth = null;
AssignPayReportsToDeposit.SelectedMonths = 0;
AssignPayReportsToDeposit.LastMonthsList = null;
AssignPayReportsToDeposit.UnAssignedPayReportsList = null;
AssignPayReportsToDeposit.AssignedPayReportsList = null;
AssignPayReportsToDeposit.LastTextChangedNode = null;
//--------- Document Ready Function -------- //
$(document).ready(function () {
//AttachEvents
AssignPayReportsToDeposit.AttachEvents();
});
AssignPayReportsToDeposit.AttachEvents = function () {
$("#ddSupplier").change(AssignPayReportsToDeposit.OnSupplierChange);
$("#ddLastMonth").change(AssignPayReportsToDeposit.OnLastMonthChange);
$("#txtMonths").change(AssignPayReportsToDeposit.OnMonthsChange);
}
//Handles Supplier ChangeEvents
AssignPayReportsToDeposit.OnSupplierChange = function () {
//Get Changed Supplier ID
AssignPayReportsToDeposit.SelectedSupplierID = $('#ddSupplier').val();
//Get Last Month List
AssignPayReportsToDeposit.LastMonthsList = CommonAction.GetLastPayReportMonthsBySupplierID(AssignPayReportsToDeposit.SelectedSupplierID);
//Fill Last Month List
AssignPayReportsToDeposit.FillLastMonths();
//Refresh TreeView_UPR
AssignPayReportsToDeposit.RefreshTreeViewUPR();
//Refresh TreeView_AD
AssignPayReportsToDeposit.RefreshTreeViewAD();
}
//Handles Last Month Change Event
AssignPayReportsToDeposit.OnLastMonthChange = function () {
AssignPayReportsToDeposit.SelectedLastMonth = $('#ddLastMonth').val();
//Refresh TreeView_UPR
AssignPayReportsToDeposit.RefreshTreeViewUPR();
//Refresh TreeView_AD
AssignPayReportsToDeposit.RefreshTreeViewAD();
}
//Handles Month Change Event
AssignPayReportsToDeposit.OnMonthsChange = function () {
AssignPayReportsToDeposit.SelectedMonths = $('#txtMonths').val();
//Refresh TreeView_UPR
AssignPayReportsToDeposit.RefreshTreeViewUPR();
//Refresh TreeView_AD
AssignPayReportsToDeposit.RefreshTreeViewAD();
}
//Fills Last Month Dropdown with options
AssignPayReportsToDeposit.FillLastMonths = function () {
var ddLastMonth = $("#ddLastMonth");
if (ddLastMonth != undefined) {
ddLastMonth.empty();
if (AssignPayReportsToDeposit.LastMonthsList != undefined) {
$.each(AssignPayReportsToDeposit.LastMonthsList, function () {
Common.AddOptionToSelect(ddLastMonth, this.Text, this.Text);
});
ddLastMonth.val(AssignPayReportsToDeposit.LastMonthsList[0].Text);
AssignPayReportsToDeposit.SelectedLastMonth = ddLastMonth.val();
}
}
}
AssignPayReportsToDeposit.ValidateControls = function () {
var success = true;
if (AssignPayReportsToDeposit.SelectedSupplierID == undefined ||
AssignPayReportsToDeposit.SelectedSupplierID == 0) {
// bootbox.alert('Please select a Supplier');
success = false;
}
else if (AssignPayReportsToDeposit.SelectedLastMonth == undefined ||
AssignPayReportsToDeposit.SelectedLastMonth == '') {
// bootbox.alert('Please select Last Month');
success = false;
}
else if (AssignPayReportsToDeposit.SelectedMonths == undefined ||
AssignPayReportsToDeposit.SelectedMonths == 0) {
// bootbox.alert('Please Enter Months');
success = false;
}
return success;
}
//Assigns DepositIdToPayReport
AssignPayReportsToDeposit.AssignDepositIdToPayReport = function (PayReportID, DepositID) {
var success = false;
if (PayReportID != undefined && DepositID != undefined) {
var jsonData = JSON.stringify({ PayReportID: PayReportID, DepositID: DepositID });
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: 'AssignPayReportToDeposit/AssignDepositIdToPayReport',
data: jsonData,
async: false,
success: function (result) {
success = result;
},
error: Common.AjaxErrorHandler
});
}
return success;
}
//--------- Tree View UPR Functions -------- //
//Gets UnAssigned Pay Reports
AssignPayReportsToDeposit.GetUnAssignedPayReports = function () {
var payReports;
if (AssignPayReportsToDeposit.ValidateControls()) {
var jsonData = JSON.stringify(
{
SupplierID: AssignPayReportsToDeposit.SelectedSupplierID,
MonthPaid: AssignPayReportsToDeposit.SelectedLastMonth,
Months: AssignPayReportsToDeposit.SelectedMonths
});
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "AssignPayReportToDeposit/GetUnAssignedPayReports",
data: jsonData,
async: false,
success: function (data) {
if (data != undefined && data != "")
payReports = data;
},
error: Common.AjaxErrorHandler
});
}
return payReports;
}
AssignPayReportsToDeposit.BindTreeViewUPR = function () {
var treeview = $("#TreeView_UPR");
var inline = new kendo.data.HierarchicalDataSource({
data: AssignPayReportsToDeposit.UnAssignedPayReportsList,
schema: {
model: {
id: "PayReportID"
}
}
});
treeview.kendoTreeView({
dragAndDrop: true,
dataSource: inline,
dataBound: function (e) {
if (!this.dataSource.data().length) {
this.element.append("<p class='no-items'>No items yet.</p>");
} else {
this.element.find(".no-items").remove();
}
},
dataTextField: ["DisplayValue"],
drop: AssignPayReportsToDeposit.OnTreeViewUPRDrop
});
}
AssignPayReportsToDeposit.OnTreeViewUPRDrop = function (e) {
var isTargetTreeViewAD = false;
var sourceDataItem = this.dataItem(e.sourceNode);
var targetDataItem = this.dataItem(e.destinationNode);
if (targetDataItem == undefined) {
targetDataItem = $("#TreeView_AD").data("kendoTreeView").dataItem(e.destinationNode);
isTargetTreeViewAD = true;
}
if (sourceDataItem == undefined ||
targetDataItem == undefined) {
//Source and target both must exists
e.preventDefault();
return;
}
if (sourceDataItem.IsDeposit == true) {
//Deposits cannot be drag and Drop
e.preventDefault();
return;
}
if (isTargetTreeViewAD) {
if (e.dropPosition == "over" &&
sourceDataItem.IsPayReport == true &&
sourceDataItem.IsAssignedPayReport == false &&
targetDataItem.IsDeposit == true) {
//Source must UnAssigned Payreport Target Must be Deposit and Drop position must over
//Implement logic to assign deposit id to the Pay Report
var PayReportID = sourceDataItem.PayReportID;
var DepositID = targetDataItem.DepositID;
if (AssignPayReportsToDeposit.AssignDepositIdToPayReport(PayReportID, DepositID)) {
sourceDataItem.set("DepositID", DepositID);
sourceDataItem.set("IsAssignedPayReport", true);
}
else {
//Didnt update the record don't do the drop
e.preventDefault();
return;
}
}
else {
e.preventDefault();
return;
}
}
else {
if ((e.dropPosition == "before" || e.dropPosition == "after") &&
sourceDataItem.IsPayReport == true &&
targetDataItem.IsPayReport == true &&
targetDataItem.IsAssignedPayReport == false) {
//Only allow sorting in this condition otherwise cancel drop event
//Means only allow sorting of unassigned payreports within the tree
}
else {
e.preventDefault();
return;
}
}
}
AssignPayReportsToDeposit.RefreshTreeViewUPR = function () {
//Destroy and empty tree
var treeview = $("#TreeView_UPR").data("kendoTreeView");
if (treeview != undefined) { treeview.destroy(); }
treeview = $("#TreeView_UPR");
treeview.empty();
AssignPayReportsToDeposit.UnAssignedPayReportsList = AssignPayReportsToDeposit.GetUnAssignedPayReports();
AssignPayReportsToDeposit.BindTreeViewUPR();
}
//--------- TreeView_AD Functions -------- //
//Gets Assigned Pay Reports
AssignPayReportsToDeposit.GetAssignedPayReports = function () {
var payReports;
if (AssignPayReportsToDeposit.ValidateControls()) {
var jsonData = JSON.stringify(
{
SupplierID: AssignPayReportsToDeposit.SelectedSupplierID,
MonthPaid: AssignPayReportsToDeposit.SelectedLastMonth,
Months: AssignPayReportsToDeposit.SelectedMonths
});
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "AssignPayReportToDeposit/GetAssignedPayReports",
data: jsonData,
async: false,
success: function (data) {
if (data != undefined && data != "")
payReports = data;
},
error: Common.AjaxErrorHandler
});
}
return payReports;
}
AssignPayReportsToDeposit.BindTreeViewAD = function () {
var treeview = $("#TreeView_AD");
var inline = new kendo.data.HierarchicalDataSource({
data: AssignPayReportsToDeposit.AssignedPayReportsList,
schema: {
model: {
id: "DepositID",
hasChildren: "HasAnyAssignedPayReports",
children: "AssignedPayReports"
}
}
});
treeview.kendoTreeView({
dragAndDrop: true,
dataSource: inline,
dataBound: function (e) {
if (!this.dataSource.data().length) {
this.element.append("<p class='no-items'>No items yet.</p>");
} else {
this.element.find(".no-items").remove();
}
},
dataTextField: ["DisplayValue", "DisplayValue"],
drop: AssignPayReportsToDeposit.OnTreeViewADDrop,
select: AssignPayReportsToDeposit.OnTreeViewADSelect
});
}
AssignPayReportsToDeposit.OnTreeViewADSelect = function (e) {
var dataItem = this.dataItem(e.node);
var treeview = this;
if (AssignPayReportsToDeposit.LastTextChangedNode != undefined) {
//Restore last node's Text
var previousDataItem = this.dataItem(AssignPayReportsToDeposit.LastTextChangedNode);
if (previousDataItem != undefined) {
var date = AssignPayReportsToDeposit.FormatDepositMonthToDisplay(previousDataItem.DepositDate);
var displaytext = "[" + date + "]" + "-[" + previousDataItem.BankName + "]-" + "[" + previousDataItem.Amount + "]";
this.text(AssignPayReportsToDeposit.LastTextChangedNode, displaytext);
}
AssignPayReportsToDeposit.LastTextChangedNode = undefined;
}
if (dataItem.IsDeposit) {
if (dataItem.hasChildren > 0) {
dataItem.set("expanded", true);
//Append sum to selected node's diplay value
var childs = dataItem.children.data();
var sum = 0;
$.each(childs, function () { sum += this.Amount });
var date = AssignPayReportsToDeposit.FormatDepositMonthToDisplay(dataItem.DepositDate);
var displaytext = "[" + date + "]" + "-[" + dataItem.BankName + "]-" + "[" + dataItem.Amount + "(" + sum + ")" + "]";
this.text(e.node, displaytext)
AssignPayReportsToDeposit.LastTextChangedNode = e.node;
}
}
}
AssignPayReportsToDeposit.FormatDepositMonthToDisplay = function (jsondate) {
var depositedate = "";
if (jsondate != undefined && jsondate != "") {
var date = Common.ParseDate(jsondate);
var month = ("0" + (date.getMonth() + 1)).slice(-2);
depositedate = date.getFullYear() + "-" + (month);
}
return depositedate;
}
AssignPayReportsToDeposit.OnTreeViewADDrop = function (e) {
var isTargetTreeViewURP = false;
var DroptoNoItemZone = false;
var sourceDataItem = this.dataItem(e.sourceNode);
var targetDataItem = this.dataItem(e.destinationNode);
var treeview_UPR = $("#TreeView_UPR").data("kendoTreeView");
if (targetDataItem == undefined) {
targetDataItem = treeview_UPR.dataItem(e.destinationNode);
if (treeview_UPR.element.find(".no-items").length > 0) DroptoNoItemZone = true;
isTargetTreeViewURP = true;
}
if ((sourceDataItem == undefined ||
targetDataItem == undefined) && DroptoNoItemZone == false) {
e.preventDefault();
return;
}
if (sourceDataItem.IsDeposit == true) {
//Deposits can not be moved within the tree view
e.preventDefault();
return;
}
if (isTargetTreeViewURP) {
if (((e.dropPosition == "before" || e.dropPosition == "after") &&
sourceDataItem.IsPayReport == true &&
sourceDataItem.IsAssignedPayReport == true &&
targetDataItem.IsPayReport == true) || (e.dropPosition == "over" && DroptoNoItemZone)) {
//Implement logic to unassing deposit id to PayReport
var PayReportID = sourceDataItem.PayReportID;
var DepositID = 0;
if (AssignPayReportsToDeposit.AssignDepositIdToPayReport(PayReportID, DepositID)) {
sourceDataItem.set("DepositID", DepositID);
sourceDataItem.set("IsAssignedPayReport", false);
}
else {
//Didnt update the record don't do the drop
e.preventDefault();
return;
}
}
else {
e.preventDefault();
return;
}
}
else {
if (e.dropPosition == "over" &&
sourceDataItem.IsPayReport == true &&
targetDataItem.IsDeposit == true) {
//Implement Logic to change deposit ID for assigned payreport
var PayReportID = sourceDataItem.PayReportID;
var DepositID = targetDataItem.DepositID;
if (AssignPayReportsToDeposit.AssignDepositIdToPayReport(PayReportID, DepositID)) {
sourceDataItem.set("DepositID", DepositID);
sourceDataItem.set("IsAssignedPayReport", true);
}
else {
//Didnt update the record don't do the drop
e.preventDefault();
return;
}
}
else {
e.preventDefault();
return;
}
}
}
AssignPayReportsToDeposit.RefreshTreeViewAD = function () {
//Destroy and empty tree
var treeview = $("#TreeView_AD").data("kendoTreeView");
if (treeview != undefined) { treeview.destroy(); }
treeview = $("#TreeView_AD");
treeview.empty();
AssignPayReportsToDeposit.LastTextChangedNode = undefined;
AssignPayReportsToDeposit.AssignedPayReportsList = AssignPayReportsToDeposit.GetAssignedPayReports();
AssignPayReportsToDeposit.BindTreeViewAD();
}
Unfortunately not out the box.
The Ajax extension methods are really just HTML helpers that work with other jQuery libraries. The helpers create the relavant HTML markup (such as adding custom addtributes data-*="") and the client scripts use this to determine their behaviour.
You could create your own MVC HTML helper and script library to handle change events for you however I would recommend looking at a front end framework such as Angular instead. This library would handle all the events declaratively so you don't need to waste time writing event handlers.

How to display a List of objects in C# to javascript using Google JS API in MVC3?

I have a .Net MVC3 website where I want to draw Pie Charts, but the Google Charts API or maybe JSON doesn't work right in my code and I don't know why.
I tried to refer from this sets of codes: MVC4 with Google JS API
This is my ChartController Code:
public ActionResult Sales()
{
return Json(CreateList(), JsonRequestBehavior.AllowGet);
}
public class ItemForChart
{
public String Name { get; set; }
public Int32 Qty { get; set; }
}
public IEnumerable<ItemForChart> CreateList()
{
List<ItemForChart> list = new List<ItemForChart>();
ItemForChart itm1 = new ItemForChart() { Name = "A", Qty = 1 };
ItemForChart itm2 = new ItemForChart() { Name = "B", Qty = 2 };
ItemForChart itm3 = new ItemForChart() { Name = "C", Qty = 3 };
ItemForChart itm4 = new ItemForChart() { Name = "D", Qty = 4 };
list.Add(itm1); list.Add(itm2); list.Add(itm3); list.Add(itm4);
return list;
}
This is my View Code for the Sale ActionResult
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" >
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
$.get('/Chart/Sales', {},
function (data) {
var tdata = new google.visualization.DataTable();
tdata.addColumn('string', 'Name');
tdata.addColumn('number', 'Qty');
for (var i = 0; i < data.length; i++) {
tdata.addRow([data[i].Name, data[i].Qty);
}
var options = {
title: "Sample Charts"
};
var chart1 = new google.visualization.AreaChart(document.getElementById('chart_div1'));
var chart2 = new google.visualization.LineChart(document.getElementById('chart_div2'));
var chart3 = new google.visualization.PieChart(document.getElementById('chart_div3'));
var chart4 = new google.visualization.ColumnChart(document.getElementById('chart_div4'));
chart1.draw(tdata, options);
chart2.draw(tdata, options);
chart3.draw(tdata, options);
chart4.draw(tdata, options);
});
}
</script>
<div id="chart_div1" style="width: 900px; height: 500px;">
</div>
<div id="chart_div2" style="width: 900px; height: 500px;">
</div>
<div id="chart_div3" style="width: 900px; height: 500px;">
</div>
<div id="chart_div4" style="width: 900px; height: 500px;">
</div>
And when I run the program, it shows this,
[{"Name":"A","Qty":1},{"Name":"B","Qty":2},{"Name":"C","Qty":3},{"Name":"D","Qty":4}]
^it doesn't show any charts but only that.
or if there are other Charts API that I can use that is also easy to learn, I am open for suggestion.
It seems like you are browsing to the JSON controller endpoint localhost/MyApp/Chart/Sales (which is consumed by the Ajax callback in google.setOnLoadCallback to feed data to the chart) - it looks like the JsonRresult is working fine. In order to view the Graph, you'll need to browse to the "Sale ActionResult" route (something like localhost/MyApp/SomeController/Sale)
You also have a typo:
for (var i = 0; i < data.length; i++) {
tdata.addRow([data[i].Name, data[i].Qty]);
// ^ closing array brace
}
Fixed jsFiddle
Not directly related, but note that you can use Object initializer syntax on the server C# to simplify matters:
public IEnumerable<ItemForChart> CreateList()
{
return new List<ItemForChart>
{
new ItemForChart() { Name = "A", Qty = 1 },
new ItemForChart() { Name = "B", Qty = 2 },
new ItemForChart() { Name = "C", Qty = 3 },
new ItemForChart() { Name = "D", Qty = 4 }
}
}

eval for parsing JSON giving undefined

I am working on Grails framework. I have 2 domain classes Country and City with one-to-many relationship. My idea is when the page is loaded the gsp will have two select boxes, one populating the countries and when any country selected the cities of that country are populated in second select box. here i am using grails ajax (jquery).
import grails.converters.JSON
class CountryController {
def index() { redirect action: 'getCountries' }
def getCountries() {
def countries = Country.list()
render view:'list', model:[countries:countries]
}
def getCities() {
def country = Country.get(params.id)
render country?.city as JSON
}
}
When getCities action is fired i am getting the JSON as below:
[
{
"class":"com.samples.City",
"id":3,
"country":{
"class":"Country",
"id":2
},
"description":"California",
"name":"California"
},
{
"class":"com.samples.City",
"id":4,
"country":{
"class":"Country",
"id":2
},
"description":"Dalls",
"name":"Dalls"
}
]
But from my gsp page when evaluating JSON with eval function, its returning "undefined".
<g:select name="countrySelect" from="${countries}"
optionKey="id" optionValue="name"
noSelection="[null:'Select Country']"
onchange="${
remoteFunction(action: 'getCities',
update: message,
params: '\'id=\' + this.value',
onSuccess:'updateCity(data)')
}"/>
<br/>
City :: <g:select name="city" id="city" from=""></g:select>
Following code in tag
<head>
<g:javascript library="jquery"></g:javascript>
<g:javascript>
function updateCity(data) {
alert('done');
var cities = eval("(" + data.responseText + ")") // evaluate JSON
alert(cities)
var rselect = document.getElementById('city')
// Clear all previous options
var l = rselect.length
while (l > 0) {
l--
rselect.remove(l)
}
//build cities
for(var i=0; i < cities.length; i++) {
var opt = document.createElement('option');
opt.text = cities[i].name
opt.value = cities[i].id
try{
rselect.add(opt,null) //For Non IE
}catch(ex){
rselect.add(opt) //For IE
}
}
}
</g:javascript>
<r:layoutResources />
</head>
Can anyone help me finding out where is the problem?
I got it solved by using JQuery each method on JSON data.
<g:javascript>
function updateCity(data) {
var rselect = document.getElementById('city')
$.each(data, function(index, element) {
//alert(element.name);
var opt = document.createElement('option');
if(element.name !== undefined){
opt.text = element.name
opt.value = element.id
try{
rselect.add(opt,null) //For Non IE
}catch(ex){
rselect.add(opt) //For IE
}
}
});
}
</g:javascript>

Dynamic javascript in ASP.Net MVC 3.0+Razor

I have a javascript that must generate in runtime.The text of script is generate in controller class :
private string mapString
{
get
{
Locations loc = new Locations();
string appPath = Request.ApplicationPath;
loc.ReadXml(Path.Combine(Request.MapPath(appPath) + "\\App_Data", "Locations.xml"));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < loc.Specfications.Count; i++)
{
sb.Append("var myLatLng" + i.ToString() + "= new google.maps.LatLng(" + loc.Specfications[i].Y.ToString() + "," +
loc.Specfications[i].X.ToString() + ");");
sb.Append(" var beachMarker" + i.ToString() + " = new google.maps.Marker({position: myLatLng" + i.ToString() + ",map: map,icon: image,title:'" + loc.Specfications[i].Title + "'});");
....
...
...
ViewData["MapString"] = mapString;
When I use it in script tag :
<script type="text/javascript">
function initialize() {
#Server.HtmlDecode(ViewData["MapString"].ToString())
}
</script>
It dosen't return a true text and it retruns something like this:
contentString0 = '<table width="100%" style="font-family: tahoma; text-align: right; font
**update : The site didn't show my question correctly ,I want to show "'<" but it show "'<"
but it must return :
contentString0 ='
you see that it convert "'<" to "'<" .
But when I use : #Server.HtmlDecode(ViewData["MapString"].ToString()) out of script tag ,all things is OK.
You may want to do it this way, which I think is going to be more flexible than generating code in your controller :
Controller action :
public JsonResult GetCoords()
{
// your code here - im putting a generic result you may
// need to put some logic here to retrieve your location / locations
var result = new { lon = "51.0000", lat = "23.0000" };
return Json(result, JsonRequestBehavior.AllowGet);
}
in your view add :
<script type="text/javascript">
$(document).ready(function () {
$.getJSON('/YourController/GetCoords', function (jsonData) {
var lon = jsonData.lon;
var lat = jsonData.lat;
yourGoogleMapFunction(lon, lat);
});
});
</script>

ajax add_endRequest never fires, on iPad only

I have some asp code in which I have a set of Telerik grids on separate jQueryUI tabs, and I am lazy-loading the grid data so that the grids only bind to live data if you actually view the tab that contains them. The rebind causes an ajax postback, and I have added an endRequest handler to re-apply the jQueryUI formatting once the request returns. This is working in Firefox, Chrome, Safari, and IE. But on the iPad the endRequest handler never fires. Any suggestions on how to troubleshoot this?
My code is as follows:
<script language="javascript" type="text/javascript">
(function ($, Sys) {
function setUpEmsDashboard() {
$('#emsDashboard').dnnTabs().dnnPanels();
$('#dInvoiceLink').click(function () {
lazyLoadOutstandingInvoicesGrid();
});
if ($('#dInvoice').is(':visible')) {
lazyLoadOutstandingInvoicesGrid();
}
$('#dCountsForStaffLink').click(function () {
lazyLoadCountsForStaffGrids();
});
if ($('#dCountsForStaff').is(':visible')) {
lazyLoadCountsForStaffGrids();
}
}
$(document).ready(function () {
setUpEmsDashboard();
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function () {
setUpEmsDashboard();
});
});
} (jQuery, window.Sys));
</script>
<telerik:RadCodeBlock ID="RadCodeBlock1" runat="server">
<script language="javascript" type="text/javascript">
function lazyLoadOutstandingInvoicesGrid() {
var grid = $find("<%=OutstandingInvoicesGrid.ClientID%>");
var masterTableView = grid.get_masterTableView();
var name = masterTableView.get_name();
if (name == 'Temp Data') {
masterTableView.rebind();
}
return true;
}
function lazyLoadCountsForStaffGrids() {
var countsBySalesRegionGrid = $find("<%=CountsBySalesRegionGrid.ClientID%>");
var cbsrMasterTableView = countsBySalesRegionGrid.get_masterTableView();
var cbsrName = cbsrMasterTableView.get_name();
if (cbsrName == 'Temp Data') {
cbsrMasterTableView.rebind();
return true;
}
var countsBySupplierTypeGrid = $find("<%=CountsBySupplierTypeGrid.ClientID%>");
var cbstMasterTableView = countsBySupplierTypeGrid.get_masterTableView();
var cbstName = cbstMasterTableView.get_name();
if (cbstName == 'Temp Data') {
cbstMasterTableView.rebind();
return true;
}
var countsByCategoryGrid = $find("<%=CountsByCategoryGrid.ClientID%>");
var cbcMasterTableView = countsByCategoryGrid.get_masterTableView();
var cbcName = cbcMasterTableView.get_name();
if (cbcName == 'Temp Data') {
cbcMasterTableView.rebind();
}
return true;
}
</script>
</telerik:RadCodeBlock>
Never mind, I found the issue. What I had was a race condition where for some browsers in some circumstances, the grid objects were null.
I changed:
function lazyLoadOutstandingInvoicesGrid() {
var grid = $find("<%=OutstandingInvoicesGrid.ClientID%>");
var masterTableView = grid.get_masterTableView();
var name = masterTableView.get_name();
if (name == 'Temp Data') {
masterTableView.rebind();
}
return true;
}
to:
function lazyLoadOutstandingInvoicesGrid() {
var grid = $find("<%=OutstandingInvoicesGrid.ClientID%>");
if (typeof (grid) !== 'undefined' && grid != null) {
var masterTableView = grid.get_masterTableView();
var name = masterTableView.get_name();
if (name == 'Temp Data') {
masterTableView.rebind();
}
return true;
}
}
...and made similar changes to the other function. That prevented the object reference error that had been silently causing the rest of the main function to fail. Now it works consistently.

Resources