Knockout JSON null when received from service - wcf

I have an object which I wish to send to a WCF service, but object dosent get properly converted to be used on the other side as the ActiveFarmer and Evidence are always null. I have tested it with a hardcoded JSON and it works but the knockout object is not coming through properly, the object is as follows
self.afi = {
ActiveFarmer: {
ActiveFarmerID: ko.observable(),
BusinessID: ko.observable(),
Year: ko.observable(),
StatusID: ko.observable(),
Status:ko.observable(),
DecisionDate: ko.observable(),
UserID: ko.observable(""),
DateModified: ko.observable(),
// RowStatus: ko.observable(""),
},
// TODO - RH we used to add a default empty new line here...
ActiveFarmerEvidence: ko.observableArray(),
NotepadIdentifiers: ko.observableArray()
};
I am calling a wcf service
public int UpdateFarmerInfo(ActiveFarmerInfo afi)
{
return ActiveFarmerInfoManager.UpdateFarmerInfo(afi);
}
My ajax call is as follows
var afi = vm.afi;
$.ajax({
type: "POST",
contentType: "application/json",
url: rootcap + "ActiveFarmerService.svc/rest/UpdateFarmer",
data: JSON.stringify(afi),
dataType: "json",
async: true,
cache: false,
success: function (data, textStatus) {
self.populateFarmerDetails(data);
},
error: function (data, status, error) { }
});
The entire view model is
function ActiveFarmerModel() {
var self = this;
self.businessId = ko.observable();
self.individualId = ko.observable();
self.currentAppId = ko.observable();
self.userId = ko.observable();
self.evidenceCategories = ko.observableArray();
self.activeFarmerEvidenceCategories = ko.observableArray();
self.businessStatus = ko.observableArray([{ "intStatusID": "2", "vcrStatus": "Provisionally Non-Oct" }, { "intStatusID": "1", "vcrStatus": "Active" }, { "intStatusID": "3", "vcrStatus": "Negative List" }, { "intStatusID": "4", "vcrStatus": "Active (Non Verified)" }])
self.currentStatus = ko.observable();
self.oldStatus = self.currentStatus();
self.ActiveFarmerID = ko.observable();
self.currentYear = ko.observable();
self.years = ko.observableArray([{ "intYearID": "5", "year": "2014" }, { "intYearID": "6", "year": "2015" }]);
self.businessStartDate = ko.observable();
self.DateFromServer = ko.observable(moment(new Date()).format('L')),
self.individualDOB = ko.observable();
self.businessName = ko.observable();
self.countyOfficeId = ko.observable();
self.individualDetails = ko.observable();
self.indDobOuterHTML = ko.observable();
self.evidenceTypes = ko.observableArray();
self.evidenceItem = function (evidenceData) {
var self = this;
if (evidenceData === null) {
self.EvidenceCategoryID = ko.observable(-1);
self.DateModified = ko.observable(moment(new Date()).format('L'));
self.DateReceipted = ko.observable(moment(new Date()).format('L'));
self.DocReceiptID = ko.observable("");
self.EvidenceID = ko.observable(-1);
self.EvidenceTypeID = ko.observable(-1);
self.Other = ko.observable("");
self.ReceiptedBy = ko.observable("");
//self.RowStatus = ko.observable("I");
self.TrimRecord = ko.observable("");
self.TrimRecordDocReceipt = ko.observable("");
self.UserID = ko.observable('NIGOV\1284535');
self.selectedCategory = ko.observable(6);
}
else {
self.EvidenceCategoryID = ko.observable(6);
self.DateModified = ko.observable(moment(evidenceData.DateModified).format('L'));
self.DateReceipted = ko.observable(moment(evidenceData.DateReceipted).format('L'));
self.DocReceiptID = ko.observable(evidenceData.DocReceiptID);
self.EvidenceID = ko.observable(evidenceData.EvidenceID);
self.EvidenceTypeID = ko.observable(evidenceData.EvidenceTypeID);
self.Other = ko.observable(evidenceData.Other);
self.ReceiptedBy = ko.observable(evidenceData.ReceiptedBy);
self.RowStatus = ko.observable(evidenceData.RowStatus);
self.TrimRecord = ko.observable(evidenceData.TrimRecord);
self.TrimRecordDocReceipt = ko.observable(evidenceData.TrimRecordDocReceipt);
self.UserID = ko.observable(evidenceData.UserID);
self.selectedCategory = ko.observable(6)
}
self.filteredSubCategories = ko.computed(function () {
self.EvidenceCategoryID = self.selectedCategory();
var ret = ko.observableArray();
var filterAll = ko.observableArray();
ret().push({ EvidenceTypeID: -1, EvidenceTypeDescription: "Please Select..." });
if (self.selectedCategory()) {
filterAll = ko.utils.arrayFilter(vm.evidenceTypes(), function (item) {
return item.EvidenceCategoryID === self.selectedCategory();
});
for (var i = 0; i < filterAll.length; i++) {
ret().push(
{
EvidenceTypeID: filterAll[i].EvidenceTypeID,
EvidenceTypeDescription: filterAll[i].EvidenceTypeDescription,
EvidenceCategoryID: filterAll[i].EvidenceCategoryID
});
};
return ret();
}
return [];
}, self);
};
self.NotePad = {
notes: ko.observableArray([
{ DateOfEntry: "01/05/2014", UserName: "John", EntryType: "Change Status", NoteText: "Status Changes to Active(Non Verified)" }
])
};
// Active Farmer Information
self.afi = {
ActiveFarmer: {
ActiveFarmerID: ko.observable(),
BusinessID: ko.observable(),
Year: ko.observable(),
StatusID: ko.observable(),
Status:ko.observable(),
DecisionDate: ko.observable(),
UserID: ko.observable(),
DateModified: ko.observable(),
},
ActiveFarmerEvidence: ko.observableArray(),
NotepadIdentifiers: ko.observableArray()
};
}
public class ActiveFarmerInfo
{
public ActiveFarmerInfo()
{
}
protected override string GetSchemaName()
{
return "ActiveFarmer";
}
[XmlIgnore]
public int ActiveFarmerID { get; set; }
[DataMember, XmlElement]
public ActiveFarmer ActiveFarmer { get; set; }
// To contain the list for Active Farmer Application Evidences based on Active Farmer Id and Year
[DataMember, XmlElement]
public List<Evidence> ActiveFarmerEvidence { get; set; }
public Int32 BusinessId { get; set; }
public Int32 Year { get; set; }
}

All the properties of the view model are knockout observable functions. So calling JSON.stringify to a view model with that kind of properties will not produce valid json. Try changing JSON.strngify to ko.toJSON This function produces valid json string from a knockout view model. Something like this:
var afi = vm.afi;
$.ajax({
type: "POST",
contentType: "application/json",
url: rootcap + "ActiveFarmerService.svc/rest/UpdateFarmer",
data: ko.toJSON(afi),
dataType: "json",
async: true,
cache: false,
success: function (data, textStatus) {
self.populateFarmerDetails(data);
},
error: function (data, status, error) { }
});
Notice the data property of the object passed to $.ajax function.

Related

Send back FullCalendar events to .NET with AJAX

I would like to sendback FullCalendar events to .NET with an AJAX request. I create a custom button for that :
#{
ViewData["Title"] = "Planning visites";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>#ViewData["Title"]</h1>
<div id='calendar'></div>
#section scripts
{
<script>
let date = new Date();
let month = String(date.getMonth() + 1).padStart(2, '0');
let day = String(date.getDate()).padStart(2, '0');
let year = date.getFullYear();
let dateDuJour = year + '-' + month + '-' + day;
let dateDuJourplusunan = (year + 1) + '-' + month + '-' + day;
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
//themeSystem: 'bootstrap5',
//plugins: [ timeGridPlugin ],
initialView: 'timeGridWeek',
selectable: true,
selectOverlap: false,
//selectMirror: true,
validRange: {
start: dateDuJour,
end: dateDuJourplusunan
},
customButtons: {
enregistrermodifs: {
text: 'enregistrer',
click: function() {
var eventsobj = calendar.getEvents();
var data = JSON.stringify(eventsobj);
//var data = JSON.serialize(eventsobj);
alert(data);
$.ajax({
type: 'POST',
url: '#Url.Action("MAJAgenda","Agenda")',
//contentType: 'application/x-www-form-urlencoded; charset=UTF-8', // when we use .serialize() this generates the data in query string format. this needs the default contentType (default content type is: contentType: 'application/x-www-form-urlencoded; charset=UTF-8') so it is optional, you can remove it
contentType: 'application/json; charset=utf-8',
data: data,
success: function(result) {
alert('Successfully received Data ');
console.log(result);
},
error: function() {
alert('Erreur : enregistrement non effectué');
console.log('Failed');
}
});
}
}
},
headerToolbar: {
left: 'prev,next,today,enregistrermodifs',
center: 'title',
right: 'dayGridMonth,timeGridWeek,dayGridDay'
},
buttonText: {
today: 'Aujourdhui',
month: 'mois',
week: 'semaine',
timeGridWeek: 'jour',
day: 'jour',
list: 'liste'
},
initialDate: dateDuJour,
navLinks: true, // can click day/week names to navigate views
editable: true,
dayMaxEvents: true, // allow "more" link when too many events
events:'#Url.Action("RecupDonneesAgenda","Agenda")?annonceId=#ViewBag.AnnonceId',
select: function(info) {
calendar.addEvent({
//id: info.startStr,
title: 'Indisponibilité',
start: info.startStr,
end: info.endStr,
allDay: false
});
},
eventClick: function(info) {
var eventobj = info.event;
eventobj.remove();
}
});
calendar.render();
calendar.setOption('locale', 'fr');
});
</script>
}
Here's my model in .NET :
public class AgendaAJAX
{
public string? title { get; set; }
public DateTime? start { get; set; }
public DateTime? end { get; set; }
}
And here's my action method :
[HttpPost]
public async Task<IActionResult> MAJAgenda(AgendaAJAX? agenda)
{
string userID = User.FindFirstValue(ClaimTypes.NameIdentifier);
////List<Agenda> agenda = await _context.Agendas.Where(a => a.AnnonceID == annonceId && a.Personne1 == userID).ToListAsync();
//JsonResult result = new JsonResult(agenda);
return View("Agenda");
}
THE AJAX call works well : here's the JSON data :
[{"title":"Indisponibilité","start":"2022-06-09T07:30:00+02:00","end":"2022-06-09T12:30:00+02:00"},{"title":"Indisponibilité","start":"2022-06-10T10:00:00+02:00","end":"2022-06-10T15:00:00+02:00"},{"title":"Indisponibilité","start":"2022-06-11T07:00:00+02:00","end":"2022-06-11T09:30:00+02:00"}]
The problem is that I don't receive any data in the action method : agenda remains null.
I don't understand why.
If you can help me please.
Thanks.

ASP.NET CORE MVC With Google Charts - No Data

Trying to implement Google Chart with ASP.Net CORE MVC.
Been at it for two days, but I can not figure out my mistake. I don't get an error, and I can see the array in the console, but no data.
VIEWMODEL
public class ZipCodes
{
public string ZipCode { get; set; }
public int ZipCount { get; set; }
}
CONTROLLER
public ActionResult IncidentsByZipCode()
{
var incidentsByZipCode = (from o in _context.Incident
group o by o.ZipCode into g
orderby g.Count() descending
select new
{
ZipCode = g.Key,
ZipCount = g.Count()
}).ToList();
return Json(incidentsByZipCode);
}
VIEW
function IncidentsByZipCode() {
$.ajax({
type: 'GET',
url: '#Url.Action("IncidentsByZipCode", "Controller")',
success: function (response) {
console.log(response);
var data = new google.visualization.DataTable();
data.addColumn('string', 'ZipCode');
data.addColumn('number', 'ZipCount');
for (var i = 0; i < response.result.length; i++) {
data.addRow([response.result[i].ZipCode, response.result[i].ZipCount]);
}
var chart = new google.visualization.ColumnChart(document.getElementById('incidentsByZipCode'));
chart.draw(data,
{
title: "",
position: "top",
fontsize: "14px",
chartArea: { width: '100%' },
});
},
error: function () {
alert("Error loading data!");
}
});
}
Because the api you use is not Column Chart, the data cannot be added and rendered correctly. According to the official example, you need to make some changes.
Here is the ajax code.
<script>
//Generate random colors
function bg() {
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
return "rgb(" + r + ',' + g + ',' + b + ")";
}
function IncidentsByZipCode() {
$.ajax({
type: 'GET',
url: '#Url.Action("IncidentsByZipCode","home")',
success: function (response) {
google.charts.load('current', { packages: ['corechart'] });
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
var obj = [
["Element", "Density", { role: "style" }],
];
$.each(response, function (index, value) {
obj.push([value.zipCode, value.zipCount, bg()])
})
var data = google.visualization.arrayToDataTable(obj);//This is method of Column Chart
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2]);
var chart = new google.visualization.ColumnChart(document.getElementById('incidentsByZipCode'));
chart.draw(data,
{
title: "",
position: "top",
fontsize: "14px",
chartArea: { width: '100%' },
});
}
},
error: function () {
alert("Error loading data!");
}
});
}
IncidentsByZipCode()
This is the controller.
public ActionResult IncidentsByZipCode()
{
//var incidentsByZipCode = (from o in _context.Incident
// group o by o.ZipCode into g
// orderby g.Count() descending
// select new
// {
// ZipCode = g.Key,
// ZipCount = g.Count()
// }).ToList();
var incidentsByZipCode = new List<ZipCodes>
{
new ZipCodes{ ZipCode="code1", ZipCount=3},
new ZipCodes{ZipCode="code2",ZipCount=4},
new ZipCodes{ZipCode="code3",ZipCount=2},
new ZipCodes{ZipCode="code4",ZipCount=9},
};
return Json(incidentsByZipCode);
}
Result, and you can also refer to this document
.

Fine Uploader - objectProperties - Key

I have 1 page whick give to user add new car to his cars collection.
User MUST to add minimum 1 image to this car item.
In AWS S3 service I save images in this path architecture:
bucket_name/cars/HERE_IS_USER_ID/HERE_IS_CAR_ID/and here photos
I use fine uploader.
ANd If i do add car in 2 step - all is going good
In 1 step I add to my database car - and send from server side userId and new car Id.
And then in step 2 I init Fine uploader with this id:
Below Code:
(function () {
'use strict';
angular
.module('cars.services.fineUploader', ['ngResource'])
.factory('FineUploader', ['$resource', '$http', 'AppConfig', function ($resource, $http, AppConfig) {
return function (divId, templateName, autoUpload, foldersBtn, uploadSuccessCallback, type, parentId, id) {
var key = '';
var keyExist = false;
getKey();
if (!qq.supportedFeatures.folderSelection) {
document.getElementById(foldersBtn).style.display = "none";
}
var uploader = new qq.s3.FineUploader({
element: document.getElementById(divId),
template: templateName,
autoUpload: autoUpload,
request: {
endpoint: 'carsbucket.s3.amazonaws.com',
accessKey: 'ACCESS',
},
extraButtons: [
{
element: document.getElementById(foldersBtn),
folders: true
}
],
signature: {
endpoint: AppConfig.apiUrl + 'api/AmazonS3/GetSignature'
},
uploadSuccess: {
endpoint: uploadSuccessCallback()
},
iframeSupport: {
localBlankPagePath: '/success.html'
},
objectProperties: {
key: function (id) {
var fileName = uploader.getName(id);
var ext = qq.getExtension(fileName);
return key+ '/' + fileName + "." + ext;
}
}
});
return {
Uploader: function () {
return uploader;
},
StartUpload: function () {
uploader.uploadStoredFiles();
},
InitUploader: function () {
while (!keyExist) {
getKey();
}
}
};
function getKey() {
var itemRequest = {
"ItemType": type,
"ParentId": parentId,
"ItemId": id
};
$http.post("http://localhost:42309/api/AmazonS3/GetItemKey", itemRequest).success(function (data, status) {
key = data;
keyExist = true;
});
}
}
}]);
})();
And this is code how I init this service:
function Uploader(shopId, shopItemId) {
vm.step = 2;
uploader = FineUploader('s3FU', 'qq-template-gallery', false, 'foldersButton', testCallback, 1, shopId, shopItemId);
}
Now I want to do all ADD ITEM logic in 1 step
But I dont know how do it - because I need init FineUploader - but I dont have carId and UserId
.........

On my cardboard app trying to show total of all features actual points for each column(Release) on the header, but that is not getting displayed

On my cardboard app trying to show total of all features actual points for each column(Release) on the header, but that is not getting displayed.
See the image below the cards are my portfolioitem/feature, in particular release.
On each header with release information, below progress-bar I want to show total of all features actual points in that release.
Below is the code for that, I am not getting why actual_points are not getting displayed. I am doing something wrong, but I don't know where exactly it is
Ext.override(Rally.ui.cardboard.CardBoard,{
_buildColumnsFromModel: function() {
var me = this;
var model = this.models[0];
if (model) {
if ( this.attribute === "Release" ) {
var retrievedColumns = [];
retrievedColumns.push({
value: null,
columnHeaderConfig: {
headerTpl: "{name}",
headerData: {
name: "Backlog"
}
}
});
this._getLocalReleases(retrievedColumns, this.globalVar);
}
}
},
_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){
console.log("records values", records);
var start_date = Rally.util.DateTime.formatWithNoYearWithDefault(record.get('ReleaseStartDate'));
var end_date = Rally.util.DateTime.formatWithNoYearWithDefault(record.get('ReleaseDate'));
//this._getMileStones(record.get('ReleaseStartDate'), record.get('ReleaseDate'), this.project);
iteration_names.push(record.get('Name'));
//iteration_names.push(record.get('ReleaseDate'));
retrievedColumns.push({
value: record,
_planned_velocity: 0,
_actual_points: 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,
actual_points: 0,
missing_estimate: false
}
}
});
});
this._getAllReleases(retrievedColumns,iteration_names);
},
scope: this
}
});
},
_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 actual_points = record.get('LeafStoryPlanEstimateTotal') || 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]._actual_points += actual_points;
retrievedColumns[index+1]._planned_velocity += planned_velocity;
});
this.fireEvent('columnsretrieved',this,retrievedColumns);
this.columnDefinitions = [];
_.map(retrievedColumns,this.addColumn,this);
this._renderColumns();
},
scope: this
}
});
}
});
Ext.define('Rally.technicalservices.plugin.ColumnHeaderUpdater', {
alias: 'plugin.tscolumnheaderupdater',
extend: 'Ext.AbstractPlugin',
config: {
/**
*
* #type {String} The name of the field holding the card's estimate
*
* Defaults to c_FeatureEstimate (try LeafStoryPlanEstimateTotal)
*/
field_to_aggregate: "planned_velocity",
/**
* #property {Number} The current count of feature estimates
*/
total_feature_estimate: 0,
fieldToDisplay: "actual_points",
/**
* #property {String|Ext.XTemplate} the header template to use
*/
headerTpl: new Rally.technicalservices.template.LabeledProgressBarTemplate({
fieldLabel: 'Features Planned vs Planned Velocity: ',
calculateColorFn: function(data) {
if ( data.percentDone > 0.9 ) {
return '#EDB5B1';
}
return '#99CCFF';
},
showDangerNotificationFn: function(data) {
return data.missing_estimate;
},
generateLabelTextFn: function(data) {
if ( data.percentDone === -1 ) {
return "No Planned Velocity";
} else {
var text_string = "";
if ( data.field_to_aggregate === "planned_velocity" ) {
text_string = this.calculatePercent(data) + '%';
} else {
text_string = 'By Story: ' + this.calculatePercent(data) + '%';
}
return text_string;
}
}
})
//headerTpl: '<div class="wipLimit">({total_feature_estimate} of {planned_velocity})</div>'
},
constructor: function(config) {
this.callParent(arguments);
if(Ext.isString(this.headerTpl)) {
this.headerTpl = Ext.create('Ext.XTemplate', this.headerTpl);
}
},
init: function(column) {
this.column = column;
if ( column.value === null ) {
this.headerTpl = new Ext.XTemplate('');
}
this.planned_velocity = this.column._planned_velocity;
this.missing_estimate = this.column._missing_estimate;
this.actual_points = this.column._actual_points;
this.column.on('addcard', this.recalculate, this);
this.column.on('removecard', this.recalculate, this);
this.column.on('storeload', this.recalculate, this);
this.column.on('afterrender', this._afterRender, this);
this.column.on('ready', this.recalculate, this);
this.column.on('datachanged', this.recalculate, this);
},
destroy: function() {
if(this.column) {
delete this.column;
}
},
_afterRender: function() {
if ( this.feature_estimate_container ) {
this.feature_estimate_container.getEl().on('click', this._showPopover, this);
}
},
recalculate: function() {
this.total_feature_estimate = this.getTotalFeatureEstimate();
this.refresh();
},
refresh: function() {
var me = this;
if (this.feature_estimate_container) {
this.feature_estimate_container.update(this.headerTpl.apply(this.getHeaderData()));
} else {
this.feature_estimate_container = Ext.widget({
xtype: 'container',
html: this.headerTpl.apply(this.getHeaderData())
});
this.column.getColumnHeader().getHeaderTitle().add(this.feature_estimate_container);
}
if ( this.feature_estimate_container && this.feature_estimate_container.getEl()) {
this.feature_estimate_container.getEl().on('click', this._showPopover, this);
}
},
_showPopover: function() {
var me = this;
if ( me.planned_velocity > 0 ) {
if ( this.popover ) { this.popover.destroy(); }
this.popover = Ext.create('Rally.ui.popover.Popover',{
target: me.column.getColumnHeader().getHeaderTitle().getEl(),
items: [ me.getSummaryGrid() ]
});
this.popover.show();
}
},
getSummaryGrid: function() {
var me = this;
var estimate_title = "Feature Estimates";
if ( this.field_to_aggregate !== "c_FeatureEstimate") {
estimate_title = "Story Estimates";
}
var store = Ext.create('Rally.data.custom.Store',{
data: [
{
'PlannedVelocity': me.planned_velocity,
'ActualPoints': me.actual_points,
'TotalEstimate': me.getTotalFeatureEstimate(),
'Remaining': me.getCapacity(),
'MissingEstimate': me.missing_estimate
}
]
});
var grid = Ext.create('Rally.ui.grid.Grid',{
store: store,
columnCfgs: [
{ text: 'Plan', dataIndex:'PlannedVelocity' },
{ text: estimate_title, dataIndex: 'TotalEstimate' },
{ text: 'Remaining', dataIndex: 'Remaining' },
{ text: 'Team Missing Plan?', dataIndex: 'MissingEstimate' }
],
showPagingToolbar: false
});
return grid;
},
getHeaderData: function() {
var total_feature_estimate = this.getTotalFeatureEstimate();
actual_points = 0;
var percent_done = -1;
planned_velocity = 20;
if ( planned_velocity > 0 ) {
percent_done = total_feature_estimate / 4;
}
return {
actual_points: actual_points,
total_feature_estimate: total_feature_estimate,
planned_velocity: planned_velocity,
percentDone: percent_done,
field_to_aggregate: this.field_to_aggregate,
missing_estimate: this.missing_estimate
};
},
getCapacity: function() {
return this.planned_velocity - this.getTotalFeatureEstimate();
},
getTotalFeatureEstimate: function() {
var me = this;
var total = 0;
var total_unaligned = 0;
var records = this.column.getRecords();
Ext.Array.each(records, function(record){
var total_points = record.get('AcceptedLeafStoryPlanEstimateTotal');
var feature_estimate = record.get(me.field_to_aggregate) || 0;
var unaligned_estimate = record.get('UnalignedStoriesPlanEstimateTotal') || 0;
total += parseFloat(total_points,10);
});
if ( me.field_to_aggregate !== "planned_velocity" ) {
total = total
}
return total;
}
});

Change Value of a dojo tree node

I'm trying to change the value of a dojo tree to display the correct icon. I was hopping that I could get the object with fetchItemByIdentity() and change the value there but the item is null
_target: null,
_treeModel: null,
constructor: function(target, uuid) {
this._target = target;
this._uuid = uuid;
// from somewhere else the value get's changed
topic.subscribe("questionChanged", lang.hitch(this, function(object, id) {
var item = this._treeModel.fetchItemByIdentity({
identifier: id,
onItem: function(item, request) { alert("item " + item); }
});
}));
},
buildTree: function() {
xhr.get({
// The URL to request
url: er.getAbsoluteUrl("/secure/staticquestion/tree?uuid=" + this._uuid),
handleAs: "json",
headers: {
"Content-Type": "application/json; charset=utf-8"
},
preventCache: 'true',
// The method that handles the request's successful result
load: lang.hitch(this, function(response) {
var rawdata = new Array();
rawdata.push(response);
var store = new ItemFileReadStore({
data: {
identifier: "uuid",
label: "name",
items: rawdata
}
});
this._loadtree(store);
}),
error: function(err, ioArgs) {
errorDialog.show(err.message);
}
});
},
_loadtree: function(store) {
this._treeModel = new TreeStoreModel({
store: store,
query: {
name: 'root'
},
childrenAttrs: [ "children" ],
mayHaveChildren: function(object) {
return object.children.length > 0;
}
});
var tree = new Tree({ // create a tree
model: this._treeModel, // give it the model
showRoot: false,
getIconClass: function(/* dojo.data.Item */item, /* Boolean */opened) {
if (!item || this.model.mayHaveChildren(item)) {
return opened ? "dijitFolderOpened" : "dijitFolderClosed";
} else if (item.comment == 'false') {
return (item.answer == 'YES') ? "dijitLeafNoCommentYes"
: ((item.answer == 'NO') ? "dijitLeafNoCommentNo" : "dijitLeafNoComment");
} else if (item.comment == 'true') {
return (item.answer == 'YES') ? "dijitLeafYes" : ((item.answer == 'NO') ? "dijitLeafNo"
: "dijitLeaf");
}
return "dijitLeaf";
},
}, this._target); // target HTML element's id
tree.on("click", function(object) {
topic.publish("staticQuestionSelected", object);
}, true);
tree.startup();
}
I'm glad for help, thanks!
Ok, I found my issue: I need to use a ItemFileWriteStore and there I can change values with store.setValue(item, attribute, value). The tree updates itself afterwards.