Custom rendering of Agile Central grid field - rally

I'm trying to create a custom grid with columns for Feature Predecessors and Successors.
I've managed to extract the data and display the relevant formatted IDs of the pre+suc in clear text. Now I would like to format these as "standard" FormattedIDs with QDP/click options.
My display looks like this, is this the right path, what should I return in order to have correct formatting?
var myGrid = Ext.create('Ext.Container', {
items: [
{
xtype: 'rallygrid',
columnCfgs: [
'FormattedID',
'Name',
{ // Column 'Successors'
xtype: 'templatecolumn',
tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate'),
dataIndex: 'Successors',
renderer: function(value, metaData, record) {
//console.log('Display in renderer: ', record.successorStore);
var mFieldOutputSuc = '';
var i;
var mDependency;
for (i = 0; i < record.successorStore.getCount(); i++) {
mDependency = record.successorStore.getAt(i);
console.log('mDependency = ', mDependency);
mFieldOutputSuc = mFieldOutputSuc + mDependency.get('FormattedID') + '<br>'; // Correct return value?
}
return mFieldOutputSuc;
}, //renderer: function(value, metaData, record) {
}, // Column 'Successors'

I'd check out this utility method: https://help.rallydev.com/apps/2.1/doc/#!/api/Rally.nav.DetailLink-method-getLink
You should be able to just put that in there where you have your //Correct return value? comment:
mFieldOutputSuc += Rally.nav.DetailLink.getLink({
record: mDependency
});
There are some more config options you can pass as well, to customize the link further, but I think that should get you started...

Related

Dealing with concurrent rally sessions in Custom html app

I have a rally poker app which is custom html where there is a screen for Team member and a screen for Scrum Master. What I need is how to control concurrent updates from team members when they use this custom html app. As of today, the app only takes the latest updates from the user who submitted last in concurrent session. It overrides everyone else data. It would be great help if someone can post the sample code of how to check for concurrent session and stop overriding of user inputs in concurrent sessions. Thanks for your help.
Click here for Scrum Master View Screenshot
#kyle - I tried to add Version ID as mentioned by you
Thanks Kyle. I did tried a cumbersome way of checking the versionID by repeating the fetch code however in my testing, it proved that versionID wasnt setting properly for concurrent sessions. I have pasted the code snippet which has the versionID check. Can you please review and let me know if anything needs to be added. Appreciate your help
Ext.create('Ext.window.Window', {
title: 'Planning Poker-Team Member view UserStoryNumber : '+userstorynumber, height: 200, width: 400, layout: 'fit',
items: [
//*************** START PANEL FORM 1 *******************
Ext.create('Ext.form.Panel', {
bodyPadding: 5, width: 350, url: 'save-form.php',
layout: { type: 'vbox', align: 'stretch', pack: 'start' },
defaults: { anchor: '100%' },
//Fields
defaultType: 'textfield',
items: [
{ fieldLabel: 'Estimate', name: 'Estimate', allowBlank: false, id: 'estimate' },
{ fieldLabel: 'Justification', name: 'Justification', allowBlank: false, id: 'justification' }
],
// Reset and Submit buttons
buttons: [
//{ text: 'Reset', handler: function () { this.up('form').getForm().reset(); } },
{
text: 'Submit', formBind: true, disabled: true,
handler: function () {
//alert(f_newEstimate('name','points','role','justification'));
var EstimateObject = getExistingEstimates(result);
if (EstimateObject)
console.log('Notes ************ ' + result.get('Notes'));
console.log('Stringfy ************ ' + JSON.stringify(EstimateObject));
//rec.set('PlanEstimate', estFinal);
var jsonobj = f_newEstimate(name, Ext.getCmp('estimate').getValue(), role, Ext.getCmp('justification').getValue());
console.log("json raw is", jsonobj);
//console.log("json justi is", jsonobj.justification);
console.log("PO note is", result.get('c_PONote'));
//var existingPONote = result.get('c_PONote');
//var newponote = existingPONote + ',' + jsonobj;
var CurrentVersionID;
var newVersionID;
//Exp Karthik Starts
var myStore = Ext.create('Rally.data.wsapi.Store', {
model: 'User Story',
autoLoad: true, // <----- Don't forget to set this to true! heh
filters: [
{
property: 'ObjectID',
operator: '=',
value: objectId
}
],
listeners: {
load: function (myStore, myData, success) {
CurrentVersionID = myStore.data.items["0"].data.VersionId;
console.log("Version ID is", myStore.data.items["0"].data.VersionId);
},
scope: this // This tells the wsapi data store to forward pass along the app-level context into ALL listener functions
},
fetch: ['ObjectID', 'c_PONote', 'VersionId'] // Look in the WSAPI docs online to see all fields available!
});
var existingPONote = result.get('c_PONote');
var newponote = '';
if (existingPONote.length == 0) {
newponote = '[' + jsonobj + ']';
}
else {
replacestr = ',' + jsonobj + ']';
newponote = existingPONote.replace(']', replacestr);
}
rec.set('c_PONote', newponote);
var myStore = Ext.create('Rally.data.wsapi.Store', {
model: 'User Story',
autoLoad: true, // <----- Don't forget to set this to true! heh
filters: [
{
property: 'ObjectID',
operator: '=',
value: objectId
}
],
listeners: {
load: function (myStore, myData, success) {
newVersionID = myStore.data.items["0"].data.VersionId;
console.log("Version ID is", myStore.data.items["0"].data.VersionId);
},
scope: this // This tells the wsapi data store to forward pass along the app-level context into ALL listener functions
},
fetch: ['ObjectID', 'c_PONote', 'VersionId'] // Look in the WSAPI docs online to see all fields available!
});
if (CurrentVersionID == newVersionID) {
rec.save();
}
else
{
var myStore = Ext.create('Rally.data.wsapi.Store', {
model: 'User Story',
autoLoad: true, // <----- Don't forget to set this to true! heh
filters: [
{
property: 'ObjectID',
operator: '=',
value: objectId
}
],
listeners: {
load: function (myStore, myData, success) {
newVersionID = myStore.data.items["0"].data.VersionId;
console.log("Version ID is", myStore.data.items["0"].data.VersionId);
},
scope: this // This tells the wsapi data store to forward pass along the app-level context into ALL listener functions
},
fetch: ['ObjectID', 'c_PONote', 'VersionId'] // Look in the WSAPI docs online to see all fields available!
});
var existingPONote = myStore.data.items["0"].data.c_PONote;
var newponote = '';
if (existingPONote.length == 0) {
newponote = '[' + jsonobj + ']';
}
else {
replacestr = ',' + jsonobj + ']';
newponote = existingPONote.replace(']', replacestr);
}
rec.set('c_PONote', newponote);
console.log("Concurrent versions saved", newponote);
rec.save();
}
console.log('Submit Success1');
this.up('window').close();
}
}]
All objects in WSAPI include a VersionId field which is automatically incremented on the server every time the object is updated. The way the product deals with concurrency issues is to always fetch this VersionId field. Then users can make updates locally. When users save, first the story is read again. If the VersionId is the same as it was when it was first read, the update is safe to send. If that VersionId is higher though, that means another user has updated the story in the meantime.
In the case of a conflict you can just merge your local changes into that newly read object and then try the save again. You can repeat this as needed until the user is able to perform a clean save.

Using a custom Drop Down List field to set a value in a grid

I'm trying to use the Rally 2.1 SDK to set a custom data field (c_wsjf) in a grid. I have a custom drop down list that I want to check the value of (c_TimeCrticalitySizing).
I created c_TimeCrticalitySizing as a feature card field in my Rally workspace with different string values (such as "No decay"). Every drop down list value will set the custom field to a different integer. When I try to run the app in Rally I get this error:
"Uncaught TypeError: Cannot read property 'isModel' of undefined(…)"
I'm thinking the drop down list value may not be a string.
How would I check what the type of the drop down list value is?
How could I rewrite this code to correctly check the value of the drop down list so I can set my custom field to different integers?
Here's my code block for the complete app. I'm still trying to hook up a search bar so for now I directly call _onDataLoaded() from the launch() function.
// START OF APP CODE
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
featureStore: undefined,
featureGrid: undefined,
items: [ // pre-define the general layout of the app; the skeleton (ie. header, content, footer)
{
xtype: 'container', // this container lets us control the layout of the pulldowns; they'll be added below
itemId: 'widget-container',
layout: {
type: 'hbox', // 'horizontal' layout
align: 'stretch'
}
}
],
// Entry point of the app
launch: function() {
var me = this;
me._onDataLoaded();
},
_loadSearchBar: function() {
console.log('in loadsearchbar');
var me = this;
var searchComboBox = Ext.create('Rally.ui.combobox.SearchComboBox', {
itemId: 'search-combobox',
storeConfig: {
model: 'PortfolioItem/Feature'
},
listeners: {
ready: me._onDataLoaded,
select: me._onDataLoaded,
scope: me
}
});
// using 'me' here would add the combo box to the app, not the widget container
this.down('#widget-container').add(searchComboBox); // add the search field to the widget container <this>
},
// If adding more filters to the grid later, add them here
_getFilters: function(searchValue){
var searchFilter = Ext.create('Rally.data.wsapi.Filter', {
property: 'Search',
operation: '=',
value: searchValue
});
return searchFilter;
},
// Sets values once data from store is retrieved
_onDataLoaded: function() {
console.log('in ondataloaded');
var me = this;
// look up what the user input was from the search box
console.log("combobox: ", this.down('#search-combobox'));
//var typedSearch = this.down('#search-combobox').getRecord().get('_ref');
// search filter to apply
//var myFilters = this._getFilters(typedSearch);
// if the store exists, load new data
if (me.featureStore) {
//me.featureStore.setFilter(myFilters);
me.featureStore.load();
}
// if not, create it
else {
me.featureStore = Ext.create('Rally.data.wsapi.Store', {
model: 'PortfolioItem/Feature',
autoLoad: true,
listeners: {
load: me._createGrid,
scope: me
},
fetch: ['FormattedID', 'Name', 'TimeCriticality',
'RROEValue', 'UserBusinessValue', 'JobSize', 'c_TimeCriticalitySizing']
});
}
},
// create a grid with a custom store
_createGrid: function(store, data){
var me = this;
var records = _.map(data, function(record) {
//Calculations, etc.
console.log(record.get('c_TimeCriticalitySizing'));
var timecritsize = record.get('c_TimeCriticalitySizing');
//console.log(typeof timecritsize);
var mystr = "No decay";
var jobsize = record.get('JobSize');
var rroe = record.get('RROEValue');
var userval = record.get('UserBusinessValue');
var timecrit = record.get('TimeCriticality');
// Check that demoniator is not 0
if ( record.get('JobSize') > 0){
if (timecritsize === mystr){
var priorityScore = (timecrit + userval + rroe) / jobsize;
return Ext.apply({
c_wsjf: Math.round(priorityScore * 10) / 10
}, record.getData());
}
}
else{
return Ext.apply({
c_wsjf: 0
}, record.getData());
}
});
// Add the grid
me.add({
xtype: 'rallygrid',
showPagingToolbar: true,
showRowActionsColumn: true,
enableEditing: true,
store: Ext.create('Rally.data.custom.Store', {
data: records
}),
// Configure each column
columnCfgs: [
{
xtype: 'templatecolumn',
text: 'ID',
dataIndex: 'FormattedID',
width: 100,
tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')
},
{
text: 'WSJF Score',
dataIndex: 'c_wsjf',
width: 150
},
{
text: 'Name',
dataIndex: 'Name',
flex: 1,
width: 100
}
]
});
}
});
// END OF APP CODE
The app works great until I add the if (timecritsize === mystr) conditional.
I also use console.log() to check that I've set all values for timecritsize to "No decay"

Filtering items in a rallymultiobjectpicker

I want to present the user with a checkbox list of portfolio item features which are currently assigned to a particular release.
The rallymultiobjectpicker with modelType set to portfolioitem/feature looks perfect for this, but it is unclear to me how to filter the objects that it displays.
Presumably this is in the storeConfig parameter? I've tried the following to no effect:
{
xtype: 'rallymultiobjectpicker',
modelType: 'portfolioitem/feature',
fieldLabel: 'Select Features',
storeConfig: {
filters: [{
property: 'Release.Name',
operator: '=',
value: myRelease
}]
},
}
As a workaround until the bug is fixed, you might try filtering on the load, like this:
{
xtype: 'rallymultiobjectpicker',
modelType: 'portfolioitem/feature',
fieldLabel: 'Select Features',
storeConfig: {
fetch: ['Release','Name']
},
storeLoadOptions: function(records) {
var store = this;
Ext.Array.each(store.getRecords(), function(record,idx){
var release = record.get('Release');
var name = null;
if ( !release || release.Name !== myRelease ) {
store.remove(record);
}
});
}
}
It's going to be slower because it goes and gets all the features first, but it seems to work.

Using Rally Cardboard UI to Display Predecessor/Successor Hierarchy

I'm currently trying to write a Rally app that will display the Predecessor/Successor hierarchy for a selected User Story. To illustrate, the user will select a User Story from a Chooser UI element. Then, a three-column Cardboard UI element will be generated--the leftmost column will contain all of the selected User Story's Predecessors (in card form), the middle column will contain the selected User Story's card, and the rightmost column will contain all of the selected User Story's Successors (in card form). From there, the Predecessor and Successor cards can be removed (denoting that they won't be Predecessors or Successors for the selected User Story) and new Predecessor/Successor cards can be added (denoting that they will become new Predecessors/Successors for the selected User Story).
However, my issue is this: the Cardboard UI was designed to display sets of different values for one particular attribute, but "Predecessor" and "Successor" don't fall into this category. Is there a possible way for me to display a User Story and then get its Predecessors and Successors and populate the rest of the board? I realize that it will take a substantial amount of modifications to the original board.
I've found a way to hack it so that you can do the display. Not sure if it's worth it or not and what you want to do for adding/removing, but this might help set you on the right path.
In summary, the problem is that the cardboard/column classes are designed to work with single value fields and each column that's created does an individual query to Rally based on the column configuration. You'll need to override the rallycardboard and the rallycolumn. I'll give the full html that you can paste in below, but let's hit this one piece at a time.
If nothing else, this might be a good example of how to take the source code of rally classes and make something to override them.
Data:
The existing cardboard is given a record type and field and runs off to create a column for each valid value for the field. It gets this information by querying Rally for the stories and for the attribute definitions. But we want to use our data in a slightly different way, so we'll have to make a different data store and feed it in. So we want to use a wsapidatastore to go ahead and get the record we asked for (in this example, I have a story called US37 that has predecessors and successors). In a way, this is like doing a cross-tab in Excel. Instead of having one record (37) that's related to others, we want to make a data set of all the stories and define their relationship in a new field, which I called "_column." Like this:
Ext.create('Rally.data.WsapiDataStore', {
model: "hierarchicalrequirement",
autoLoad: true,
fetch: ['Name','Predecessors','Successors','FormattedID','ObjectID','_ref'],
filters: [ {
property: 'FormattedID', operator: 'contains', value: '37'
} ] /* get the record US37 */,
listeners: {
load: function(store,data,success) {
if ( data.length === 1 ) {
var base_story = data[0].data;
var modified_records = [];
base_story._column = "base";
modified_records.push( base_story );
Ext.Array.each( base_story.Predecessors, function( story ) {
story._column = "predecessor";
modified_records.push( story );
} );
Ext.Array.each( base_story.Successors, function(story) {
story._column = "successor";
modified_records.push( story );
} );
We push the data into an array of objects with each having a new field to define which column it should go in. But this isn't quite enough, because we need to put the data into a store. The store needs a model -- and we have to define the fields in a way that the cardrenders know how to access the data. There doesn't seem to be an easy way to just add a field definition to an existing rally model, so this should do it (the rally model has unique field information and a method called getField(), so we have to add that:
Ext.define('CardModel', {
extend: 'Ext.data.Model',
fields: [
{ name: '_ref', type: 'string' },
{ name: 'ObjectID', type: 'number'},
{ name: 'Name', type: 'string', attributeDefinition: { AttributeType: 'STRING'} },
{ name: 'FormattedID', type: 'string'},
{ name: '_column', type: 'string' },
{ name: 'ScheduleState', type: 'string' } ] ,
getField: function(name) {
if ( this.data[name] ) {
var return_field = null;
Ext.Array.each( this.store.model.getFields(), function(field) {
if ( field.name === name ) {
return_field = field;
}
} );
return return_field;
} else {
return null;
}
}
});
var cardStore = Ext.create('Ext.data.Store',{
model: 'CardModel',
data: modified_records
});
Now, we'll create a cardboard, but instead of the rally cardboard, we'll make one from a class we're going to define below ('DependencyCardboard'). In addition, we'll pass along a new definition for the columns that we'll also define below ('dependencycolumn').
var cardboard = Ext.create('DependencyCardboard', {
attribute: '_column',
store: cardStore, /* special to our new cardboard type */
height: 500,
columns: [{
xtype: 'dependencycolumn',
displayValue: 'predecessor',
value: 'predecessor',
store: cardStore
},
{
xtype: 'dependencycolumn',
displayValue: 'base',
value: 'base',
store: cardStore
},
{
xtype: 'dependencycolumn',
displayValue: 'successor',
value: 'successor',
store: cardStore
}]
});
Cardboard:
Mostly, the existing Rally cardboard can handle our needs because all the querying is done down in the columns themselves. But we still have to override it because there is one function that is causing us problems: _retrieveModels. This function normally takes the record type(s) (e.g., User Story) and based on that creates a data model that is based on the Rally definition. However, we're not using the UserStory records directly; we've had to define our own model so we could add the "_columns" field. So, we make a new definition (which we use in the create statement above for "DependencyCardboard").
(Remember, we can see the source code for all of the Rally objects in the API just by clicking on the title, so we can compare the below method to the one in the base class.)
We can keep all of the stuff that the Rally cardboard does and only override the one method by doing this:
Ext.define( 'DependencyCardboard', {
extend: 'Rally.ui.cardboard.CardBoard',
alias: 'widget.dependencycardboard',
constructor: function(config) {
this.mergeConfig(config);
this.callParent([this.config]);
},
initComponent: function() {
this.callParent(arguments);
},
_retrieveModels: function(success) {
if ( this.store ) {
this.models = [ this.store.getProxy().getModel() ];
success.apply( this, arguments );
}
}
});
Column:
Each column normally goes off to Rally and says "give me all of the stories that have a field equal to the column name". But we're passing in the store to the cardboard, so we need to override _queryForData. In addition, there is something going on about defining the column height when we do this (I don't know why!) so I had to add a little catch in the getColumnHeightFromCards() method.
_queryForData: function() {
var allRecords = [];
var records = this.store.queryBy( function( record ) {
if ( record.data._column === this.getValue() ) { allRecords.push( record ); }
}, this);
this.createAndAddCards( allRecords );
},
getColumnHeightFromCards: function() {
var contentMinHeight = 500,
bottomPadding = 30,
cards = this.query(this.cardConfig.xtype),
height = bottomPadding;
for(var i = 0, l = cards.length; i < l; ++i) {
if ( cards[i].el ) {
height += cards[i].getHeight();
} else {
height += 100;
}
}
height = Math.max(height, contentMinHeight);
height += this.down('#columnHeader').getHeight();
return height;
}
Finish
So, if you add all those pieces together, you get one long html file that we can push into a panel (and that you can keep working on to figure out how to override dragging results and to add your chooser panel for the first item. (And you can make better abstracted into its own class)).
Full thing:
<!DOCTYPE html>
<html>
<head>
<title>cardboard</title>
<script type="text/javascript" src="/apps/2.0p3/sdk.js"></script>
<script type="text/javascript">
Rally.onReady(function() {
/*global console, Ext */
Ext.define( 'DependencyColumn', {
extend: 'Rally.ui.cardboard.Column',
alias: 'widget.dependencycolumn',
constructor: function(config) {
this.mergeConfig(config);
this.callParent([this.config]);
},
initComponent: function() {
this.callParent(arguments);
},
_queryForData: function() {
var allRecords = [];
var records = this.store.queryBy( function( record ) {
if ( record.data._column === this.getValue() ) { allRecords.push( record ); }
}, this);
this.createAndAddCards( allRecords );
},
getColumnHeightFromCards: function() {
var contentMinHeight = 500,
bottomPadding = 30,
cards = this.query(this.cardConfig.xtype),
height = bottomPadding;
for(var i = 0, l = cards.length; i < l; ++i) {
if ( cards[i].el ) {
height += cards[i].getHeight();
} else {
height += 100;
}
}
height = Math.max(height, contentMinHeight);
height += this.down('#columnHeader').getHeight();
return height;
}
});
/*global console, Ext */
Ext.define( 'DependencyCardboard', {
extend: 'Rally.ui.cardboard.CardBoard',
alias: 'widget.dependencycardboard',
constructor: function(config) {
this.mergeConfig(config);
this.callParent([this.config]);
},
initComponent: function() {
this.callParent(arguments);
},
_retrieveModels: function(success) {
if ( this.store ) {
this.models = [ this.store.getProxy().getModel() ];
success.apply( this, arguments );
}
}
});
/*global console, Ext */
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
items: [ { xtype: 'container', itemId: 'outer_box' }],
launch: function() {
Ext.create('Rally.data.WsapiDataStore', {
model: "hierarchicalrequirement",
autoLoad: true,
fetch: ['Name','Predecessors','Successors','FormattedID','ObjectID','_ref'],
filters: [ {
property: 'FormattedID', operator: 'contains', value: '37'
} ],
listeners: {
load: function(store,data,success) {
if ( data.length === 1 ) {
var base_story = data[0].data;
var modified_records = [];
base_story._column = "base";
modified_records.push( base_story );
Ext.Array.each( base_story.Predecessors, function( story ) {
story._column = "predecessor";
modified_records.push( story );
} );
Ext.Array.each( base_story.Successors, function(story) {
story._column = "successor";
modified_records.push( story );
} );
Ext.define('CardModel', {
extend: 'Ext.data.Model',
fields: [
{ name: '_ref', type: 'string' },
{ name: 'ObjectID', type: 'number'},
{ name: 'Name', type: 'string', attributeDefinition: { AttributeType: 'STRING'} },
{ name: 'FormattedID', type: 'string'},
{ name: '_column', type: 'string' },
{ name: 'ScheduleState', type: 'string' } ] ,
getField: function(name) {
if ( this.data[name] ) {
var return_field = null;
Ext.Array.each( this.store.model.getFields(), function(field) {
if ( field.name === name ) {
return_field = field;
}
} );
return return_field;
} else {
return null;
}
}
});
var cardStore = Ext.create('Ext.data.Store',{
model: 'CardModel',
data: modified_records
});
var cardboard = Ext.create('DependencyCardboard', {
attribute: '_column',
store: cardStore,
height: 500,
columns: [{
xtype: 'dependencycolumn',
displayValue: 'predecessor',
value: 'predecessor',
store: cardStore
},
{
xtype: 'dependencycolumn',
displayValue: 'base',
value: 'base',
store: cardStore
},
{
xtype: 'dependencycolumn',
displayValue: 'successor',
value: 'successor',
store: cardStore
}]
});
this.down('#outer_box').add( cardboard );
}
},
scope: this
}
});
}
});
Rally.launchApp('CustomApp', {
name: 'cardboard'
});
});
</script>
<style type="text/css">
.app {
/* Add app styles here */
}
</style>
</head>
<body></body>
</html>

Sencha Touch 1.1. I need to populate a Ext.List Object from an Array Javascript variable, instead of a Proxy

I am working in sencha touch 1.1, specifically, using Ext.List. But instead of using a proxy to populate the Ext.List object, I need to load the data right straight from an array javascript variable like
var = [["1","Ángel Quezada"],["2","Christian Herrera"],["3","Francisco Quispe"]]
I don't have any trouble populating the Ext.List in the proxy way, first I declare le model, then the proxy and finally the List. According the next lines.
Ext.regModel('Cronograma', {
idProperty: 'nrocuota',
fields: [{name:'nrocuota', type: 'string'}]
});
Ext.regStore('CronogramaStore', {
model: 'Cronograma',
proxy: {
type :'ajax',
url: '/mSAS/cotizacion.do?method=generarCronograma',
reader: {type:'array'}
}
});
this.grdCronograma = new Ext.List({
id: 'notesList',
store: 'CronogramaStore',
emptyText: 'No existe resultado ',
itemTpl: '{nrocuota}',
listeners: {'render':function(thisComponent){}}
});
But right know I have another need. I need to populate the List from an Array Javascript Variable, not using the proxy, I mean
how can I use the
var varArray = [["1","Ángel Quezada"],["2","Christian Herrera"],["3","Francisco Quispe"]]
to populate the Ext.List, I guess there's a way using the Ext.data.Store and its load method. but I can't find it.
Here is dynamic way of doing it, without using static data.
Ext.regModel('Cronograma', {
idProperty: 'nrocuota',
fields: [{name:'nrocuota', type: 'string'}]
});
Ext.regStore('CronogramaStore', {
model: 'Cronograma'/*,
data : [
{ nrocuota : 'Ángel Quezada' },
{ nrocuota : 'Christian Herrera' },
{ nrocuota : 'Francisco Quispe' }] */ // Does not take array [[],[],[]] that was specified in problem statement
});
this.grdCronograma = new Ext.List({
id: 'notesList',
store: 'CronogramaStore',
emptyText: 'No existe resultado ',
itemTpl: '{nrocuota}',
listeners: {'render':function(thisComponent){}}
});
// Here is the dynamic method.
function addToList(data){
var len = data.length;
for(var i=0;i<len;i++){
var note = Ext.ModelMgr.create({
nrocuota: data[i][1], //grab only name from the array
}, 'Cronograma');
CronogramaStore.add(note);
CronogramaStore.sync();
}
}
//now just call the function
var data = [["1","Ángel Quezada"],["2","Christian Herrera"],["3","Francisco Quispe"]];
addToList(data);
Ext.regModel('Cronograma', {
idProperty: 'nrocuota',
fields: [{name:'nrocuota', type: 'string'}]
});
Ext.regStore('CronogramaStore', {
model: 'Cronograma',
data : [
{ nrocuota : 'Ángel Quezada' },
{ nrocuota : 'Christian Herrera' },
{ nrocuota : 'Francisco Quispe' }
]
});
this.grdCronograma = new Ext.List({
id: 'notesList',
store: 'CronogramaStore',
emptyText: 'No existe resultado ',
itemTpl: '{nrocuota}',
listeners: {'render':function(thisComponent){}}
});
update to use arrays instead of json object:
Ext.regModel('Cronograma', {
idProperty: 'id',
fields: [ 'id', 'nrocuota' ]
});
var data = [["1","Ángel Quezada"],["2","Christian Herrera"],["3","Francisco Quispe"]];
Ext.regStore('CronogramaStore', {
model: 'Cronograma',
data : data
});
this.grdCronograma = new Ext.List({
id: 'notesList',
store: 'CronogramaStore',
emptyText: 'No existe resultado ',
itemTpl: '{nrocuota}',
listeners: {'render':function(thisComponent){}}
});
or already indicated if you don't have data available at time of creation of store then use store.loadData(data); function
i haven't tested this code myself so if it's not working then please tell me