Can you tell me PageSize Change Event in Kendo Angular grid - angularjs

Can you tell me page size Change event in Kendo-Angular grid as i am new in kendo grid control. Please help me. Thank you in advance.
app.controller("dataController", function ($compile, dataFactory, $scope, $timeout) {
$scope.obj = [];
$scope.DistrictList = [];
$scope.DistrictTextToShow = "Select District";
$scope.GetDistrict = function () {
dataFactory.getdistrictList().success(function (data) {
$scope.DistrictList = data;
}).error(function (data) {
$.toaster({ priority: 'error', title: 'Error', message: 'Error while fetching data' });
});
};
if ($("#ddldistrict").val() == '') {
$scope.ddldistrict = GuidEmpty;
}
else {
$scope.ddldistrict = $("#ddldistrict").val();
}
$scope.gridData = new kendo.data.DataSource({
serverPaging: true,
serverSorting: true,
transport: {
read: {
url: baselocation + "api/Customer/GetAllCustomerByDistrictId",
data: { DistrictId: $scope.ddldistrict, isactive: $("#ddlstatus").val() }
}
},
schema: {
data: function (data) {
return data.Rows;
},
total: function (data) {
return data.TotalRows;
}
},
pageSize: 5
});
$scope.detailGridOptions = {
sortable: true,
pageable: {
"pageSizes": true,
change: function (e) {
if ($("#ddldistrict").val() == '') {
$scope.ddldistrict = GuidEmpty;
}
else {
$scope.ddldistrict = $("#ddldistrict").val();
}
//$("#grid1").data('kendoGrid').dataSource.pageSize(parseInt(this.value()));
$("#grid1").data('kendoGrid').dataSource.read({ DistrictId: $scope.ddldistrict, isactive: $("#ddlstatus").val() });
$("#grid1").data('kendoGrid').refresh();
}
},
datasource: $scope.gridData,
groupable: true,
scrollable: true,
columns: [{
field: "Customername",
title: "Customer Name",
width: "150px"
}, {
field: "mobile",
title: "Mobile",
width: "120px"
}, {
field: "email",
title: "Email",
width: "120px"
}, {
field: "Districtname",
title: "District",
width: "120px"
}]
};
$scope.GetDistrict();
$scope.BindData = function () {
if ($("#ddldistrict").val() == '') {
$scope.ddldistrict = GuidEmpty;
}
else {
$scope.ddldistrict = $("#ddldistrict").val();
}
$("#grid1").data('kendoGrid').dataSource.read({ DistrictId: $scope.ddldistrict, isactive: $("#ddlstatus").val() });
$("#grid1").data('kendoGrid').refresh();
}
//$("#grid1").kendoPager({
//});
//$scope.gridData.read();
});

Related

How can I find length of kendo dataSource?

I am trying to find length of kendo grid dataSource, but I am always getting 0 in return. How can I get the total length of dataSource? I have added Control service that is dataSource for the grid.
ctrl.js
$scope.alignedProcessesToControlGridOptions.dataSource = ControlRatingGridDataService.getAlignedProcessesToControlGrid($stateParams.controlId);
var data = $scope.alignedProcessesToControlGridOptions.dataSource.data().length;
console.log('GRID DATA', data);
DataService.js
getAlignedProcessesToControlGrid: function(controlKey) {
var countNew = 0;
return new kendo.data.DataSource({
type: 'json',
serverPaging: true,
serverSorting: true,
serverFiltering: true,
transport: {
read: function(options) {
var gridSearchObject = {
skip: options.data.skip,
take: options.data.take,
pageSize: options.data.pageSize,
page: options.data.page,
sorting: options.data.sort,
filter: options.data.filter
};
return $http.post(
'app/control/rest/allAlignedProcessesToControl/' + controlKey, gridSearchObject).success(
function(data) {
countNew = data.totalCount;
options.success(data.resultDTOList);
});
}
},
pageSize: 5,
schema: {
model: {
id: 'riskInProcessKey',
fields: {
processName: {
editable: false
},
epcfName: {
editable: false
},
erhName: {
editable: false
},
ctlGeolocationsText: {
editable: false
},
ctlPerformanceRatingText: {
editable: false
},
ctlEffectivenessRatingText: {
editable: false
}
}
},
total: function() {
return countNew;
}
}
});
},
Assuming your HTML for the grid looks something like...
$("#grid").kendoGrid({
dataSource: {
// your datasource
},
dataBound: onDataBound
});
Create a function for the dataBound event...
function onDataBound(e) {
console.log(e.sender.dataSource.view().length);
}

Struggling to write a Jasmine testcase for AngularJS

The below code is my controller logic and I want to create a Jasmine test case for it. With $inject I am getting problem how to mock or use the services used in $inject and write a Jasmine test case for below AngularJS controller logic.
(function () {
'use strict';
var controllerId = 'user';
angular.module('app').controller(controllerId, user);
user.$inject = ['$rootScope', 'userService', 'common'];
function user($rootScope, $userService, common) {
var vm = this;
vm.users = [];
vm.sorting = {
column: "UpdatedDate",
order: 0
};
vm.gridHeaders = [
{ title: "UserName", visible: true, sort: true, name: 'UserName', filter: true, type: 'string' },
{ title: "First Name", visible: true, sort: true, name: 'FirstName', filter: true, type: 'string' },
{ title: "Middle Name", visible: true, sort: true, name: 'MiddleName', filter: true, type: 'string' },
{ title: "Last Name", visible: true, sort: true, name: 'LastName', filter: true, type: 'string' },
{ title: "Email Address", visible: true, sort: true, name: 'EmailID', filter: true, type: 'string' },
{ title: "Phone Number", visible: true, sort: true, name: 'PhoneNumber', filter: true, type: 'string' },
{ title: "Mobile Number", visible: true, sort: true, name: 'MobileNumber', filter: true, type: 'string' },
{ title: "City", visible: true, sort: true, name: 'City', filter: true, type: 'string' },
{ title: "Role", visible: true, sort: true, name: 'RoleID', filter: true, type: 'int' },
{ title: "Address", visible: true, sort: true, name: 'Address', filter: true, type: 'string' },
{ title: "UserType", visible: true, sort: true, name: 'UserType', filter: true, type: 'int' },
{ title: "RoleName", visible: true, sort: true, name: 'RoleName', filter: true, type: 'string' }
];
vm.editUser = function (value) {
if (value > 0) {
var request = [{
"PageNumber": vm.pagination.currentPage,
"PageSize": vm.pagination.pageSize,
"SortColumn": vm.sorting.column,
"SortOrder": vm.sorting.order,
"Query": "UserID=" + value
}];
$userService.sendUserID(request);
}
}
vm.loadUserSearchDetails = function () {
//common.showSpinngMan();
var pageConstants = common.preparePageConstants();
vm.pageDropDown = pageConstants.pageDropDown;
vm.pagination = pageConstants.pagination;
loadGrid();
};
vm.loadPageData = function (scenario) {
vm.pagination.currentPage = common.setPagination(scenario, vm.pagination)
loadGrid();
};
//Load grid
var loadGrid = function (data) {
var request = [{
"PageNumber": vm.pagination.currentPage,
"PageSize": vm.pagination.pageSize,
"SortColumn": vm.sorting.column,
"SortOrder": vm.sorting.order,
"Query": ""
// Filters: vm.filterPanel.savedFilter
}];
$rootScope.loading = true;
$userService.getUserDetails(request).then(function (result) {
debugger;
if (!!result) {
vm.users = result.SearchUsers;
vm.pagination.totalRecords = vm.users.length;
vm.pagination.totalPages = Math.ceil(vm.pagination.totalRecords / vm.pagination.pageSize);
}
}).catch(function (result) {
console.log("error load grid");
//$location.path("/error");
}).finally(function () {
$rootScope.loading = false;
})
};
return vm;
}
})();
for the above controller code i have written jasmine testcase by removing injected service userservice and common.js
the new part consists :
//user.$inject = ['$rootScope', 'userService', 'common']; //line removed
function user($rootScope) { // , $userService, common params removed
var vm = this;
vm.users = [];
commented the code relating to $userservice and written jasmine testcase like below and it's working fine.. my question is how write when i inject the other dependencies i.e. 'userservice' 'common'
describe("A suite", function () {
beforeEach(module('app'));
var $controller;
var mockServiceDepedency;
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
it("testing 5", function () {
var $rootScope = {};
var controller = $controller('user', { $rootScope: $rootScope });
expect(controller.users).not.toBeNull();
expect(controller.users).toEqual([]);
expect(controller.sorting.column).toEqual("UpdatedDate");
expect(controller.sorting.order).toEqual(0);
expect(controller.gridHeaders[0]).toEqual({ title: "UserName", visible: true, sort: true, name: 'UserName', filter: true, type: 'string' });
expect(controller.pageDropDown).not.toBeNull();
expect(controller.pageDropDown).not.toBeNull();
expect(controller.loadUserSearchDetails.pageConstants).not.toBeNull();
});
});

I wrote CardBoard Rally sdk 2 app to which I added filter but I want to add two different filter, one for releases and one for backlog

I wrote CardBoard Rally sdk 2 app to which I added filter which apply to Backlog and Releases too. But I want to add two different filters, one for releases and one for backlog
See in image attached, u can see one column for Backlog and other for releases
So I should be able to say Now filter Backlog features, and Now filter Releases features
Below is my some of code snippet
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
autoScroll: true,
all_releases: [],
items:[{ xtype: 'container', itemId: 'filter_box', padding: 5},{xtype:'container',itemId:'button_box', padding: 5}],
logger: new Rally.technicalservices.logger(),
launch: function() {
//var allReleases = this._getReleases();
this._drawCardBoard(this, filters= null);
this.down('#button_box').add({
xtype: 'rallybutton',
text: 'Filter Criteria',
itemId: 'run-button',
scope: this,
handler: this._run,
margin: '0 0 0 10'
});
this.down('#button_box').add({
xtype: 'rallybutton',
text: 'Prev',
itemId: 'prev-button',
scope: this,
handler: this._setPrevReleaseDate,
margin: '0 0 0 100'
});
this.down('#button_box').add({
xtype: 'rallybutton',
text: 'Next',
itemId: 'next-button',
scope: this,
handler: this._setNextReleaseDate,
margin: '0 0 0 650'
});
},
_setPrevReleaseDate: function() {
if (this.globalVar == undefined) {
this.globalVar = new Date();
} else {
this.globalVar = new Date(this.globalVar);
};
this.globalVar = Rally.util.DateTime.formatWithDefault(Ext.Date.subtract(this.globalVar, Ext.Date.DAY, 224));
this._drawCardBoard(this, filters= null);
},
_setNextReleaseDate: function() {
if (this.globalVar == undefined) {
this.globalVar = new Date();
} else {
this.globalVar = new Date(this.globalVar);
};
this.globalVar = Rally.util.DateTime.formatWithDefault(Ext.Date.add(this.globalVar, Ext.Date.DAY, 224));
this._drawCardBoard(this, filters= null);
},
_getFilters: function(records) {
var filters = null;
if (records.length >= 1) {
if (records[0].data.PortfolioItemTypeName == "MMF") {
filters = Ext.create('Rally.data.QueryFilter',{
property: 'Parent',
operator: '=',
value: records[0].get("_ref")
});
} else if (records[0].data.PortfolioItemTypeName == "Epic") {
filters = Ext.create('Rally.data.QueryFilter',{
property: 'Parent.Parent',
operator: '=',
value: records[0].get("_ref")
});
} else if (records[0].data.PortfolioItemTypeName == "Program") {
filters = Ext.create('Rally.data.QueryFilter',{
property: 'Parent.Parent.Parent',
operator: '=',
value: records[0].get("_ref")
});
}
for ( var i=1;i<records.length;i++ ) {
if (records[i].data.PortfolioItemTypeName == "MMF") {
filters = filters.or(Ext.create('Rally.data.QueryFilter',{
property: 'Parent',
operator: '=',
value: records[i].get("_ref")
}));
} else if (records[i].data.PortfolioItemTypeName == "Epic") {
filters = filters.or(Ext.create('Rally.data.QueryFilter',{
property: 'Parent.Parent',
operator: '=',
value: records[i].get("_ref")
}));
} else if (records[i].data.PortfolioItemTypeName == "Program") {
filters = filters.or(Ext.create('Rally.data.QueryFilter',{
property: 'Parent.Parent.Parent',
operator: '=',
value: records[i].get("_ref")
}));
}
}
}
return filters;
},
_drawCardBoard: function(that, filters){
if (that.cardboard) {
that.cardboard.destroy();
};
var me = that;
if (filters == null) {
filters = [];
}
me.cardboard = Ext.create('Rally.ui.cardboard.CardBoard',{
types: ['PortfolioItem/Feature'],
attribute: 'Release',
config: {globalVar: this.globalVar},
columnConfig: {
xtype: 'rallycardboardcolumn',
displayField: 'Name',
valueField: '_ref',
plugins: [
{ptype:'rallycolumndropcontroller'},
{ptype:'rallycardboardcardrecordprocessor'},
{ptype:'tscolumnheaderupdater'} /*,
{ptype:'tscolumnheaderupdater', field_to_aggregate: 'LeafStoryPlanEstimateTotal'}*/
],
storeConfig: {
filters: filters,
context: this.getContext().getDataContext()
}
},
addColumn: function (columnConfig, index) {
console.log(columnConfig, index,"columnConfig, index");
var column = this._createColumnDefinition(columnConfig);
Ext.Array.insert(this.columnDefinitions, Ext.isNumber(index) ? index : this.columnDefinitions.length, [column]);
return column;
},
cardConfig: {
editable: true,
showIconsAndHighlightBorder: false,
showReadyIcon: true,
showBlockedIcon: true,
showColorIcon: true,
showPlusIcon: true,
showGearIcon: true,
fields: [
'FormattedID',
'Name',
'Parent',
'ReleaseDate',
'ReleaseStartDate',
{ name: 'Project', renderer: me._renderProject },
{ name: 'PercentDoneByStoryPlanEstimate' },
{ name: 'PreliminaryEstimate', fetch: ['PreliminaryEstimate', 'Name'], renderTpl: Ext.create('Ext.XTemplate', '{PreliminaryEstimate.Name}')},
{ name: 'LeafStoryPlanEstimateTotal', fetch: ['LeafStoryPlanEstimateTotal'], renderTpl: Ext.create('Ext.XTemplate', 'Plan Estimate Total: {LeafStoryPlanEstimateTotal}')}
],
},
listeners: {
beforeShow: this._onTeamMembersLoaded,
added: function(card,container){
//card.set('DisplayColor', "blue");
me.logger.log(this,card,container);
},
fieldClick: function(eOpts) {
me.logger.log(this,eOpts);
if ( eOpts == "PercentDoneByStoryPlanEstimate" ) {
me._showDoneTooltip(eOpts,this);
}
},
scope: this
}
});
_getLocalReleases: function(retrievedColumns, today_iso) {
var me = this;
if (today_iso == undefined) {
today_iso = Rally.util.DateTime.toIsoString(new Date(),false);
}
var filters = [{property:'ReleaseDate',operator:'>',value:today_iso}];
var iteration_names = [];
Ext.create('Rally.data.WsapiDataStore',{
model:me.attribute,
autoLoad: true,
filters: filters,
context: { projectScopeUp: false, projectScopeDown: false },
sorters: [
{
property: 'ReleaseDate',
direction: 'ASC'
}
],
//limit: Infinity,
pageSize: 4,
//buffered: true,
//purgePageCount: 4,
fetch: ['Name','ReleaseStartDate','ReleaseDate','PlannedVelocity'],
listeners: {
load: function(store,records) {
Ext.Array.each(records, function(record){
var start_date = Rally.util.DateTime.formatWithNoYearWithDefault(record.get('ReleaseStartDate'));
var end_date = Rally.util.DateTime.formatWithNoYearWithDefault(record.get('ReleaseDate'));
iteration_names.push(record.get('Name'));
//iteration_names.push(record.get('ReleaseDate'));
retrievedColumns.push({
value: record,
_planned_velocity: 0,
_missing_estimate: false,
columnHeaderConfig: {
headerTpl: "{name}<br/>{start_date} - {end_date}",
headerData: {
name: record.get('Name'),
start_date: start_date,
end_date: end_date,
planned_velocity: 0,
missing_estimate: false
}
}
});
});
this._getAllReleases(retrievedColumns,iteration_names);
},
scope: this
}
});
},
applyLocalFilters: function() {
this.applyFilters(this.localFilters);
},
_getAllReleases: function(retrievedColumns,iteration_names, today_iso) {
var me = this;
if (today_iso == undefined) {
today_iso = Rally.util.DateTime.toIsoString(new Date(),false);
}
var filters = [{property:'ReleaseDate',operator:'>',value:today_iso}];
Ext.create('Rally.data.WsapiDataStore',{
model:me.attribute,
autoLoad: true,
filters: filters,
sorters: [
{
property: 'ReleaseDate',
direction: 'ASC'
}
],
fetch: ['Name','Project','PlannedVelocity'],
listeners: {
load: function(store,records) {
Ext.Array.each(records, function(record){
var planned_velocity = record.get('PlannedVelocity') || 0;
var index = Ext.Array.indexOf(iteration_names[0],record.get('Name'));
if (planned_velocity == 0 ) {
retrievedColumns[index+1]._missing_estimate = true;
}
retrievedColumns[index+1]._planned_velocity += planned_velocity;
});
this.fireEvent('columnsretrieved',this,retrievedColumns);
this.columnDefinitions = [];
_.map(retrievedColumns,this.addColumn,this);
this._renderColumns();
},
scope: this
}
});
},
_createColumnDefinition: function (columnConfig) {
var config = Ext.merge({
enableCrossColumnRanking: this.enableCrossColumnRanking
}, this.columnConfig, columnConfig);
var enableRanking = this.enableRanking;
if (this.context) {
var workspace = this.context.getWorkspace();
if (workspace) {
enableRanking = enableRanking && workspace.WorkspaceConfiguration.DragDropRankingEnabled;
}
}
var listenersConfig = {
ready: this._onColumnReady,
select: this._onCardSelect,
deselect: this._onCardDeselect,
cardinvalid: this._onCardInvalid,
cardready: this._onCardReady,
scope: this
};
if (!this.serverSideFiltering) {
listenersConfig.filter = this.applyLocalFilters;
}
Ext.merge(config, {
cardConfig: Ext.clone(this.cardConfig),
columnHeaderConfig: Ext.clone(this.columnHeaderConfig),
model: this.models,
attribute: this.attribute,
storeConfig: Ext.clone(this.storeConfig),
enableRanking: enableRanking,
filterCollection: this.filterCollection ? this.filterCollection.clone() : undefined,
ownerCardboard: this,
listeners: listenersConfig,
ddGroup: this.ddGroup
});
if (this.readOnly) {
config.dropControllerConfig = false;
}
//merge configs, unioning collections
var cardConfig = config.cardConfig;
if (columnConfig.cardConfig) {
Ext.Object.merge(cardConfig, columnConfig.cardConfig);
cardConfig.fields = Ext.Array.merge(columnConfig.cardConfig.fields || [], this.cardConfig.fields || []);
}
var storeConfig = config.storeConfig;
if (columnConfig.storeConfig) {
Ext.Object.merge(storeConfig, columnConfig.storeConfig);
storeConfig.filters = Ext.Array.merge(columnConfig.storeConfig.filters || [], this.storeConfig.filters || []);
}
console.log("columnConfig", Ext.clone(columnConfig));
console.log("storeConfig", Ext.clone(storeConfig));
return Ext.widget(config.xtype, config);
},
});
Ext.override(Rally.ui.cardboard.Card,{
_setupPlugins: function() {
var cardContentRightPlugin = {ptype: 'rallycardcontentright'};
this.plugins.push(cardContentRightPlugin);
this.plugins.push({ptype: 'rallycardcontentleft'});
if (this.record.get('updatable')) {
if (this.editable) {
this.addCls('editable');
this.plugins.push({ptype: 'rallycardediting'});
var predicateFn = Rally.predicate.RecordPredicates.hasField('PlanEstimate');
if (predicateFn(this.record) && Ext.Array.contains(this.getFields(), 'PlanEstimate')) {
cardContentRightPlugin.showPlanEstimate = true;
}
if (this.enableValidationUi) {
this.plugins.push({ptype: 'rallycardvalidation'});
this.plugins.push({ptype: 'rallycardvalidationui', notificationFieldNames: ['PlanEstimate']});
}
}
if (this.showIconsAndHighlightBorder) {
this.plugins.push({
ptype: 'rallycardicons',
showMenus: this.showIconMenus,
showColorPopover: this.showColorPopover
});
}
}
if (this.showAge > -1) {
this.plugins.push({ptype: 'rallycardage'});
}
this.plugins.push({ptype:'tscardreleasealignment'});
}
}),
Ext.override(Rally.ui.cardboard.Column,{
getStoreFilter: function(model) {
var property = this.attribute;
var value = this.getValue();
if ( this.attribute == "Release" ) {
property = "Release.Name";
if ( value ) {
value = value.get('Name');
}
}
return {
property:property,
operator: '=',
value: value
};
},
isMatchingRecord: function(record) {
var recordValue = record.get(this.attribute);
if (recordValue) {
recordValue = recordValue.Name;
}
var columnValue = this.getValue();
if ( columnValue ) {
columnValue = columnValue.get('Name');
}
return (columnValue === recordValue );
},
addCard: function(card, index, highlight) {
var record = card.getRecord();
var target_value = this.getValue();
if ( target_value && typeof(target_value.get) === "function" ) {
target_value = this.getValue().get('_ref');
}
record.set(this.attribute,target_value);
if (target_value) {
record.set("PlannedStartDate",this.getValue().get('ReleaseStartDate'));
record.set("PlannedEndDate",this.getValue().get('ReleaseDate'));
} else {
record.set("PlannedStartDate",null);
record.set("PlannedEndDate",null);
}
if (!Ext.isNumber(index)) {
//find where it should go
var records = Ext.clone(this.getRecords());
records.push(record);
this._sortRecords(records);
var recordIndex = 0;
for (var iIndex = 0, l = records.length; iIndex < l; iIndex++) {
var i = records[iIndex];
if (i.get("ObjectID") === record.get("ObjectID")) {
recordIndex = iIndex;
break;
}
}
index = recordIndex;
}
this._renderCard(card, index);
if (highlight) {
card.highlight();
}
this.fireEvent('addcard');
card.fireEvent('ready', card);
},

Want to call a function when chart is loaded rally

Want to call a function when chart is loaded, written that function in listeners, but its getting called before the chart is displayed, any idea which event should I listen to chartRendered or any other
getChartConfig: function(project_oid) {
that = this;
var chart = Ext.getCmp('mychart');
if (chart) {
chart.destroy();
}
return {
xtype:'rallychart',
id: 'mychart',
storeConfig: {
find: {
'_ProjectHierarchy': project_oid,
"$or": [
{"_TypeHierarchy": "HierarchicalRequirement"},
{"_TypeHierarchy": "Defect"}
],
'Children': null
},
fetch: ['PlanEstimate','_TypeHierarchy','ObjectID', 'ScheduleState', '_ValidFrom', '_ValidTo', '_PreviousValues'],
hydrate: ['ScheduleState', '_TypeHierarchy'],
sort: { '_ValidFrom': 1 }
,
/*find: {
'_ProjectHierarchy': project_oid,
"_TypeHierarchy": {
"$in": ['HierarchicalRequirement', 'Defect']
},
'Children': null
},
fetch: ['PlanEstimate','_TypeHierarchy','ObjectID', 'ScheduleState', '_ValidFrom', '_ValidTo', '_PreviousValues'],
hydrate: ['ScheduleState', '_TypeHierarchy'],
sort: { '_ValidFrom': 1 }*/
},
calculatorType: 'CycleCalculator',
chartColors: [ "#6AB17D", "#F47168", "#000000"],
calculatorConfig: {
startDate: Rally.util.DateTime.format(new Date(this._startDate), 'Y-m-d'),
endDate: Rally.util.DateTime.format(new Date(this._endDate), 'Y-m-d'),
startState: this._startState,
endState: this._endState
//granularity: 'week'
},
chartConfig: {
chart: {
type: 'line',
},
title: { text: 'Cycle/Lead Time' },
border: 1,
plotOptions: {
series: {
connectNulls: true,
marker: {
enabled:false
}
}
},
xAxis: {
//tickmarkPlacement: 'on',
tickInterval: 10,
title: {
text: 'Months'
}
},
yAxis: [
{
title: {
text: 'Average Days'
}
}
]
},
listeners: {
snapshotsAggregated: this.showStats,
scope: this
}
}
},
below the is function I want to call
And in showStats() function I want use chart object,,,,please help..thanks in advance
showStats: function(chart) {
console.log("chart values", chart);
var average = Ext.Array.mean(chart.calculator.globalVar);
var average = Ext.Number.toFixed(average, 2);
var min = Ext.Array.min(chart.calculator.globalVar);
var max = Ext.Array.max(chart.calculator.globalVar);
var count = Ext.Array.sum(chart.calculator.globalVar);
console.log("field value", average, min, max, count);
//field.fieldLabel = average;
var stdDev = this.standardDeviation(average, chart.calculator.globalVar);
var stdDev = Ext.Number.toFixed(stdDev, 2);
this.down('#averageId').setText("Average " + average);
this.down('#countId').setText("Count " + count);
this.down('#minId').setText("Minimum " + min);
this.down('#maxId').setText("Maximum " + max);
this.down('#stdDevId').setText("Std Deviation " + stdDev);
},
Your choice of chartRendered is correct- that is the last one to fire.
If it is fires before the chart is fully rendered, it is a bug, but from my tests it looks like it fires at the right time. I do not know what data is stored in your globalVar and how you arrive at it. Perhaps the problem is somewhere else other then the timing of the chartRendered event.
When I modify this example by adding chartRendered event listener, visually the console.log may log a little faster than the chart animation entirely completes, but the chart data is already fully loaded by then, and all the data is complete. I verified that by building a table with a few stats that you use. Here is the full code:
Ext.define('Rally.example.BurnCalculator', {
extend: 'Rally.data.lookback.calculator.TimeSeriesCalculator',
config: {
completedScheduleStateNames: ['Accepted']
},
constructor: function(config) {
this.initConfig(config);
this.callParent(arguments);
},
getDerivedFieldsOnInput: function() {
var completedScheduleStateNames = this.getCompletedScheduleStateNames();
return [
{
"as": "Planned",
"f": function(snapshot) {
if (snapshot.PlanEstimate) {
return snapshot.PlanEstimate;
}
return 0;
}
},
{
"as": "PlannedCompleted",
"f": function(snapshot) {
if (_.contains(completedScheduleStateNames, snapshot.ScheduleState) && snapshot.PlanEstimate) {
return snapshot.PlanEstimate;
}
return 0;
}
}
];
},
getMetrics: function() {
return [
{
"field": "Planned",
"as": "Planned",
"display": "line",
"f": "sum"
},
{
"field": "PlannedCompleted",
"as": "Completed",
"f": "sum",
"display": "column"
}
];
}
});
var PI_OID = 12483739639; //The ObjectID of the PI on which to burn
Ext.define('Rally.example.BurnChart', {
extend: 'Rally.app.App',
requires: [
'Rally.example.BurnCalculator'
],
launch: function() {
this.add({
xtype: 'rallychart',
storeType: 'Rally.data.lookback.SnapshotStore',
storeConfig: this._getStoreConfig(),
calculatorType: 'Rally.example.BurnCalculator',
calculatorConfig: {
completedScheduleStateNames: ['Accepted', 'Released']
},
chartConfig: this._getChartConfig(),
listeners:{
chartRendered: this._getStats,
scope: this
}
});
},
/**
* Generate the store config to retrieve all snapshots for all leaf child stories of the specified PI
*/
_getStoreConfig: function() {
return {
find: {
_ItemHierarchy: PI_OID,
_TypeHierarchy: 'HierarchicalRequirement',
Children: null
},
fetch: ['ScheduleState', 'PlanEstimate'],
hydrate: ['ScheduleState'],
sort: {
_ValidFrom: 1
},
context: this.getContext().getDataContext(),
limit: Infinity
};
},
/**
* Generate a valid Highcharts configuration object to specify the chart
*/
_getChartConfig: function() {
return {
chart: {
defaultSeriesType: 'area',
zoomType: 'xy'
},
title: {
text: 'PI Burnup'
},
xAxis: {
categories: [],
tickmarkPlacement: 'on',
tickInterval: 5,
title: {
text: 'Date',
margin: 10
}
},
yAxis: [
{
title: {
text: 'Points'
}
}
],
tooltip: {
formatter: function() {
return '' + this.x + '<br />' + this.series.name + ': ' + this.y;
}
},
plotOptions: {
series: {
marker: {
enabled: false,
states: {
hover: {
enabled: true
}
}
},
groupPadding: 0.01
},
column: {
stacking: null,
shadow: false
}
}
};
},
_getStats:function(chart){
var stats = [];
console.log(chart);
var series = chart.chartData.series;
_.each(series, function(s){
stats.push({
name : s.name,
average : Ext.Number.toFixed(Ext.Array.mean(s.data), 2),
min : Ext.Array.min(s.data),
max : Ext.Array.max(s.data),
count : Ext.Array.sum(s.data)
});
});
this._showStats(stats);
},
_showStats: function(stats) {
console.log(stats);
this.add({
xtype: 'rallygrid',
store: Ext.create('Rally.data.custom.Store', {
data: stats
}),
columnCfgs: [
{
text: 'Name',
dataIndex: 'name'
},
{
text: 'Average',
dataIndex: 'average'
},
{
text: 'Min',
dataIndex: 'min'
},
{
text: 'Max',
dataIndex: 'max'
},
{
text: 'Count',
dataIndex: 'count'
}
]
});
}
});

Kendo UI Grid foreign key column using Angular directives

I'm trying to make a Kendo Grid that has 2 foreign key columns using the Angular directives for Kendo. I am able to get one to work, but not the other (independent of each other). If I comment one out the other will work and vice versa, but either way only one will work. Abbreviated sample code is below.
invoicesController.js
app.controller('invoicesController', [
'$scope', '$rootScope', 'config', 'dataFactory', function($scope, $rootScope, config, dataFactory) {
$rootScope.title = 'Invoices';
$scope.filterCustomers = [];
$scope.filterStatuses = [];
$scope.invoiceGrid = null;
var _refreshCustomers = function () {
dataFactory.get(_.string.format('{0}customers', config.apiUrl)).success(function (result) {
$scope.filterCustomers = _.map(result, function (cust, key) {
return {
text: cust.name,
value: cust.id
}
});
});
};
var _refreshStatuses = function() {
dataFactory.get(_.string.format('{0}invoicestatuses', config.apiUrl)).success(function(result) {
$scope.filterStatuses = _.map(result.data, function(status, key) {
return {
text: status.name,
value: status.id
}
});
_initializeGrid();
});
};
var _refreshData = function () {
_refreshCustomers();
_refreshStatuses();
};
_refreshData();
var _initializeGrid = function() {
$scope.invoiceGrid = {
dataSource: {
transport: {
read: _.string.format('{0}invoices', config.apiUrl),
},
schema: {
data: 'data'
},
pageSize: 15,
sort: { field: 'invoiceDate', dir: 'asc' }
},
columns: [
{ title: 'Subject', field: 'subject', type: 'string', width: '30%'},
{ title: 'Number', field: 'number', width: '12%' },
{ title: 'Customer', field: 'customer.id', values: $scope.filterCustomers, width: '15%' },
{ title: 'Status', field: 'status.id', values: $scope.filterStatuses, width: '14%' },
{ title: 'Total', field: 'invoiceTotal', type: 'number', format: '{0:c2}', width: '10%' },
{
title: 'Updated', field: 'updatedOn', type: 'date', format: '{0:d}', width: '19%',
template: '#=lastUpdated#'
}
],
scrollable: false,
sortable: true,
filterable: true,
pageable: true
};
}
}
]);
dataFactory.js (GET method)
return $http({
url: url,
method: 'GET',
data: data,
});
list.html
<div data-kendo-grid data-k-ng-delay="invoiceGrid" data-k-options="invoiceGrid" class="top"></div>
I was able to get this to work using route resolve.
Basically, when you're defining your routes, you can set resolvers. In this case, I'm resolving customers and statuses which you will also see as arguments on the projectsController
app.js (routing config)
// Projects
$routeProvider.when('/projects', {
templateUrl: '/app/views/projects/list.html',
controller: 'projectsController',
resolve: {
customers: ['customerService', function (customerService) {
return customerService.getCustomers();
}],
statuses: ['projectService', function (projectService) {
return projectService.getStatuses();
}]
}
});
projectsController.js (abbreviated)
app.controller('projectsController', [
'$scope', '$rootScope', 'config', 'customers', 'statuses', function($scope, $rootScope, config, customers, statuses) {
// Set the options from the injected statuses (from the route resolver)
$scope.statusOptions = _.map(statuses.data.data, function(status) {
return { value: status.id, text: status.name }
});
....
// Kendo grid column definition
columns: [
{ title: 'Status', field: 'status.id', values: $scope.statusOptions, width: '15%' },
]
}]);

Resources