Querying on DirectChildrenCount Rally JS SDK - extjs

I checked out some other questions posted previously but couldn't find a relevant answer. So here I am posting again: Here's my code:
Ext.create('Rally.data.WsapiDataStore',{
autoLoad: true,
model: 'HierarchicalRequirement',
limit: '500',
fetch: ['ObjectID','DirectChildrenCount','FormattedID'],
filters:[{property: 'DirectChildrenCount', operator: '=', value: 0}], //tried both "0",'0'
listeners: {
load: function(store,data,success){
var data_length = data.length;
console.log("Number = ", data);
}
}
});
Result is an empty array. Furthermore, the result did not contain the field "DirectChildrenCount" at all, even though I am fetching it.

I tried your code without any changes, and it returned 300+ items. DirectChildrenCount was included in the result. It was tested against "2.0rc2" and "2.0rc1" with the same result. Here is screenshot from Chrome's DevTools:
Here is another short app where a grid of stories updated since yesterday is built, filtered by the same condition.
{property: 'DirectChildrenCount', operator: '=', value: 0}
js file is below:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
var millisecondsInDay = 86400000;
var currentDate = new Date();
var startDate = new Date(currentDate - millisecondsInDay);
var startDateUTC = startDate.toISOString();
Rally.data.ModelFactory.getModel({
type: 'UserStory',
success: function(model) {
this.grid = this.add({
xtype: 'rallygrid',
itemId: 'grid',
model: model,
columnCfgs: [
'FormattedID',
'Name',
'Owner',
'LastUpdateDate'
],
storeConfig: {
filters: [
{
property: 'LastUpdateDate',
operator: '>',
value: startDateUTC
},
{
property: 'DirectChildrenCount',
operator: '=',
value: 0
},
]
}
});
},
scope: this
});
console.log('items updated since', startDateUTC);
}
});

Related

How to add additional keys to the itemselector keymap EXTjs?

Is there a solution to extend the KeyMap of the ItemSelector?
I would like to add a keymap(like pageUp and pageDown keyEvent in itemselector) that when I press the letter 'A-Z' will take me to the item that starts with the letter pressed and select it.
You can use the following override (fiddle sample) to achieve it. It will not work correctly on view sore reload. And you will have to define the record search record field. In case of complicated view templates you can remove hardcoded search function and use it as a setting.
Ext.define('overrides.view.NavigationModel', {
override: 'Ext.view.NavigationModel',
searchRecordField: false,
initKeyNav: function (view) {
var me = this;
// Drive the KeyNav off the View's itemkeydown event so that beforeitemkeydown listeners may veto.
// By default KeyNav uses defaultEventAction: 'stopEvent', and this is required for movement keys
// which by default affect scrolling.
var keyNavConfig = {
target: view,
ignoreInputFields: true,
eventName: 'itemkeydown',
defaultEventAction: 'stopEvent',
processEvent: me.processViewEvent,
up: me.onKeyUp,
down: me.onKeyDown,
right: me.onKeyRight,
left: me.onKeyLeft,
pageDown: me.onKeyPageDown,
pageUp: me.onKeyPageUp,
home: me.onKeyHome,
end: me.onKeyEnd,
space: me.onKeySpace,
enter: me.onKeyEnter,
A: {
ctrl: true,
// Need a separate function because we don't want the key
// events passed on to selectAll (causes event suppression).
handler: me.onSelectAllKeyPress
},
F: me.onAlphabetKeyPress,
scope: me
};
if(this.view.searchRecordField) {
keyNavConfig = Ext.Object.merge(keyNavConfig, this.getAdditionalKeyNav());
}
me.keyNav = new Ext.util.KeyNav(keyNavConfig);
},
getAdditionalKeyNav: function() {
var keyNav = {};
this.view.getStore().each(function(record) {
var firstLetter = record.get(this.view.searchRecordField)[0].toUpperCase();
if(!keyNav[firstLetter]) {
keyNav[firstLetter] = this.onAlphabetKeyPress
}
}, this);
return keyNav;
},
onAlphabetKeyPress: function(keyEvent) {
const key = keyEvent.event.key;
var foundRecordIndex = this.view.getStore().findBy(function(record) {
return record.get('title').toLowerCase().indexOf(key) === 0;
}, this);
if(foundRecordIndex > -1) {
this.setPosition(foundRecordIndex, keyEvent);
}
}
});
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('ListItem', {
extend: 'Ext.data.Model',
fields: [{
name: 'src',
type: 'string'
}, {
name: 'caption',
type: 'string'
}]
});
Ext.create('Ext.data.Store', {
id: 'ListItemsStore',
model: 'ListItem',
data: [{
title: "One"
}, {
title: "Two"
}, {
title: "Three"
}, {
title: "Four"
}, {
title: "Three"
}, ]
});
var imageTpl = new Ext.XTemplate(
'<tpl for=".">',
'<div style="margin-bottom: 10px;" class="thumb-wrap">',
'<span>{title}</span>',
'</div>',
'</tpl>'
);
Ext.create('Ext.view.View', {
store: Ext.data.StoreManager.lookup('ListItemsStore'),
tpl: imageTpl,
itemSelector: 'div.thumb-wrap',
emptyText: 'No images available',
// Search Record Field
searchRecordField: 'title',
renderTo: Ext.getBody()
});
}
});

PullRefresh plugin of a List doesn't handle ChainedStore possibility

Using Ext JS 7.1 Modern, I have prepared an example to show the problem.
When I have remote filters on my main store, binding the dataview.List to a ChainedStore correctly handles my local filtering. However, when I also add a PullRefresh plugin to the list, I get an error during pull refresh. I see from the source code that the plugin doesn't consider the possibility that a list's store can be a ChainedStore.
I have tried to explain the problem with a Sencha Fiddle and also attached the code below.
I have temporarily solved the problem by overriding the fetchLatest and onLatestFetched methods of Ext.dataview.pullrefresh.PullRefresh plugin, to use the source store if the list's store is a ChainedStore. But I believe the source code must be updated to handle this case.
app.js
Ext.define('App.model.Test', {
extend: 'Ext.data.Model',
fields: ['id', 'firstName', 'lastName']
});
Ext.define('App.store.Test', {
extend: 'Ext.data.Store',
alias: 'store.teststore',
model: 'App.model.Test'
});
Ext.define('App.viewmodel.Test', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.test',
data: {
query: ''
},
stores: {
test: {
type: 'teststore',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'names.json',
reader: {
type: 'json',
rootProperty: 'data'
}
},
remoteFilter: true,
filters: {
property: 'id',
value: 1
}
},
chained: {
type: 'chained',
autoLoad: true,
source: '{test}'
}
}
});
Ext.define('App.controller.TestController', {
extend: 'Ext.app.ViewController',
alias: 'controller.testcontroller',
doSearch: function (field) {
var list = this.lookup('list'),
store = list.getStore(),
value = field.getValue();
if (Ext.isEmpty(value)) {
store.removeFilter('firstName')
} else {
store.filter([{
property: 'firstName',
value: value,
operator: 'like'
}])
}
}
});
Ext.define('App.dataview.TestList', {
extend: 'Ext.dataview.List',
xtype: 'testlist',
viewModel: {
type: 'test'
},
plugins: [{
type: 'pullrefresh',
mergeData: false
}],
emptyText: 'Name not found',
bind: {
store: '{chained}'
},
itemTpl: '<div class="contact">{id} <b>{firstName} {lastName}</b></div>'
});
Ext.define('App.MainView', {
extend: 'Ext.Panel',
controller: 'testcontroller',
fullscreen: true,
viewModel: {
type: 'test'
},
items: [{
xtype: 'searchfield',
ui: 'solo',
placeholder: 'Search names',
listeners: {
buffer: 500,
change: 'doSearch'
},
bind: {
value: '{query}'
}
}, {
reference: 'list',
xtype: 'testlist'
}]
})
Ext.application({
name: 'App',
mainView: 'App.MainView'
});
names.json
var data = [{
id: 1,
firstName: 'Peter',
lastName: 'Venkman'
}, {
id: 2,
firstName: 'Raymond',
lastName: 'Stantz'
}, {
id: 3,
firstName: 'Egon',
lastName: 'Spengler'
}, {
id: 4,
firstName: 'Winston',
lastName: 'Zeddemore'
}]
var results = data.filter(function(record) {
if (params.filter) {
return record.id > params.filter[0].value
}
})
return {
"success": true,
"data": results
}
App.override.dataview.pullrefresh.PullRefresh:
Ext.define('App.override.dataview.pullrefresh.PullRefresh', {
override: 'Ext.dataview.pullrefresh.PullRefresh',
privates: {
fetchLatest: function() {
const store = this.getStore().isChainedStore ? this.getStore().getSource() : this.getStore()
store.fetch({
page: 1,
start: 0,
callback: this.onLatestFetched,
scope: this
});
},
onLatestFetched: function(newRecords, operation, success) {
var me = this,
list = me.getList(),
store = list.getStore().isChainedStore ? list.getStore().getSource() : list.getStore(),
length, toInsert,
oldRecords, newRecord, oldRecord, i;
if (success) {
if (me.getMergeData()) {
oldRecords = store.getData();
toInsert = [];
length = newRecords.length;
for (i = 0; i < length; i++) {
newRecord = newRecords[i];
oldRecord = oldRecords.getByKey(newRecord.getId());
if (oldRecord) {
oldRecord.set(newRecord.getData());
}
else {
toInsert.push(newRecord);
}
}
store.insert(0, toInsert);
}
else {
store.loadRecords(newRecords);
}
me.setLastUpdated(new Date());
}
me.setState('loaded');
list.fireEvent('latestfetched', me, toInsert || newRecords);
if (me.getAutoSnapBack()) {
me.snapBack(true);
}
}
}
})
Thanks in advance
Since this post, instead of being a question, was a bug report with a possible solution, it has been posted to Ext JS 7.x Community Forums\Ext JS 7.x Bugs.
The above solution, that overwrites the plugin where source store is needed, works if anyone comes across the same issue.

Loading initial configuration data on extjs

need your help on the following problem. I have an Extjs application, and I need to get some data from database at the begining of all, I mean, before everything loads (mostly views). This is because this data I need to load will be used to create a form in a specific view.
So the question is: where should I put the function that gets the data and stores it in a global variable? I tried to put that function in launch function on app.js, but the behavior is weird (sometimes loads the data before the view renders, and sometimes does it after).
Please see above the code:
Function that gets the data (placed in App.js and invoked inside launch function):
cargarItemsEvaluacion: function()
{
AppGlobals.itemsCargarFormEvaluacion = [];
Ext.Ajax.request(
{
url : 'app/proxy.evaluacion.php',
method: 'GET',
params :{
act: 'getEvalItemsForm'
},
success : function(response)
{
var obj = Ext.decode(response.responseText);
Ext.each(obj.results, function(item)
{
//console.log(item);
var tempItem = {
xtype: 'container',
layout: 'anchor',
flex: 1,
items: [
{
//xtype: 'fieldset',
title: item.nombre,
items: [
{
id: 'item_'+item.id,
xtype: 'textfield',
fieldLabel: item.descripcion,
name: 'item_'+item.id,
allowBlank: false,
blankText: 'Este campo es obligatorio',
maskRe: /^[0-9]{1}/,
maxLenght: 2,
validateOnChange: 'true',
emptyText: 'Nota (1 al 10)',
submitEmptyText: false,
validator: function(value)
{
if(value.length>2 || value>10)
{
return 'Complete con nota del 1 al 10';
}
var stringPad=/^[1-9]{1}[0-9]{0,1}/;
if (!stringPad.test(value))
{
return 'Complete con nota del 1 al 10';
}
else
{
return true;
}
}
}]
}]
};
AppGlobals.itemsCargarFormEvaluacion.push(tempItem);
});//End Ext.each
if(AppGlobals.itemsCargarFormEvaluacion.length>0)
{
var itemObservacion = {
xtype: 'container',
layout: 'anchor',
flex: 1,
items: [
{
title: 'Observaciones',
items: [
/*{
id: 'ascenso',
xtype: 'checkbox',
boxLabel: 'Recomienda ascenso',
name: 'ascenso'
},*/
{
id: 'observaciones',
xtype: 'textareafield',
grow: true,
fieldLabel: 'Agregue observaciones adicionales si lo cree necesario',
name: 'observaciones',
labelAlign: 'top'
}
]
}]
};
AppGlobals.itemsCargarFormEvaluacion.push(itemObservacion);
}
console.log(AppGlobals.itemsCargarFormEvaluacion);
},
failure: function(response)
{
var obj = Ext.decode(response.responseText);
console.log("Entra al failure "+response.responseText);
//Ext.example.msg("Error", "No se pudo comprobar si es posible cargar al evaluador. Error: "+obj.error);
}
});//End Ext.ajax
}
And this is the initComponent function on the view where I need to generate the form using the data I got from the previous function:
initComponent: function(){
var formEvaluacion = this.items[0];
if(AppGlobals.itemsCargarFormEvaluacion.length==0)
{
console.log("Data still no loaded");
}
else
{
console.log("Data loaded!");
}
console.log(AppGlobals.itemsCargarFormEvaluacion);
Ext.apply(formEvaluacion,{items: AppGlobals.itemsCargarFormEvaluacion});
this.callParent(arguments);
}
As you can see, I check if the data loads before the view renders, or after. And sometimes does it before, sometimes after...I don't know what it depends on...
Any help will be appreciated.
Mauro
Think I found the solution. I placed cargarItemsEvaluacion function into init function on app.js. Seem to be working so far.
Thanks!

ExtJs Grid Auto Refresh using REST Proxy

I have tried to refresh the Grid every 5 or 10 seconds which is using REST Proxy, but the grid is not getting refreshed more than once. Please find the code which we have tried.
Ext.define('App.Store.DeviceStore', {
extend: 'Ext.data.Store',
requires: [
'Ext.data.proxy.Ajax',
'Ext.data.reader.Json'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'app.store.DeviceStore',
model: 'App.model.DeviceModel',
activeRefreshTask:false,
pageSize: 5,
autoLoad: {
pageSize: 5
}
}, cfg)]);
},listeners:{
'load':function(store,records,successful,operation){
if(successful === true && store.activeRefreshTask === false){
var task = {
identifyId: 'deviceListStore',
run: function() {
if (App.app._currentPage == 'devicesform') {
store.reload();
} else {
Ext.TaskManager.stop(this);
}
},
interval: '10000'
}
Ext.TaskManager.start(task);
store.activeRefreshTask = true;
}
}
}
});
The model for the above store is
Ext.define('App.model.DeviceModel', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.field.String'
],
proxy:{
type:'rest',
reader: {
type: 'json',
rootProperty: 'data',
totalProperty:'total'
},
useDefaultXhrHeader: false,
headers:{'Content-Type':'application/json'},
api: {
read: 'url given gere'
}
},
fields: [
{
type: 'string',
name: 'id'
},
{
type: 'string',
name: 'name'
},
{
type: 'string',
name: 'desc'
},
{
type: 'string',
name: 'ipAddr'
}
]
});
I have found the issue , You have passed the interval as string in place lo number.
just change to interval: '10000' to inteval: 10000 and your taskrunner will runs fine.
var runner = new Ext.util.TaskRunner(),
updateStore , task;
updateStore = function() {
if (App.app._currentPage == 'devicesform') {
store.load();
} else {
Ext.TaskManager.stop(this);
}
};
task = runner.start({
run: updateStore ,
interval: 1000
});
probably your store.reload is sending again the same params on the request, so with a request that not change nothing changes.

How to create Grid in sencha touch 2.3.0 populate data from a REST webservice

I need to display report in Grid / Table in Sencha Touch 2.3.0. Is there any build in function to do so.
The store needs to populate data from a REST webservice call.
For loading data you can use Ext.data.Store configured with REST proxy Ext.data.proxy.Rest
For displaying data from store you can use Ext.grid.Grid of Ext.dataview.DataView
I do this all the time with something like this:
(Though I haven't worked with the Grid, I'm quite sure the same principles apply...)
Ext.define('App.controller.GridController', {
extend : 'Ext.app.Controller',
config: {
refs: {
getApiButton: 'button[action=getApiData]'
},
control: {
'getApiButton' : {
tap : 'onButtonTap'
}
}
},
onButtonTap : function(field, value) {
var that = this;
Ext.Ajax.request({
url : someWebServiceUrl,
method: 'GET',
success: function (result, request) {
var res = Ext.decode(result.responseText);
if (res.success === true && res.data != false) {
var recipient = {
name: res.data[0].displayname,
picId: res.data[0].pictureid,
gender: res.data[0].gender
};
var mod = Ext.define('App.model.GradingPopModel', {
extend: 'Ext.data.Model',
config: {
fields: [
'name',
'picId',
'gender'
]
}
});
/* == this is probably where you want to make your changes to apply the model to the grid template
the sencha website has this:
data: {'items': [
{ 'name': 'Lisa', "email":"lisa#simpsons.com", "phone":"555-111-1224" },
{ 'name': 'Bart', "email":"bart#simpsons.com", "phone":"555-222-1234" },
{ 'name': 'Homer', "email":"home#simpsons.com", "phone":"555-222-1244" },
{ 'name': 'Marge', "email":"marge#simpsons.com", "phone":"555-222-1254" }
]}
*/
var store = Ext.create('Ext.data.Store', {
model: mod,
storeId:'recipStore'
});
store.add(recipient);
store.setData(recipient);
store.load();
var gridView = Ext.ComponentQuery.query('#gridViewId')[0];
gridView.setStore(store);
}
},
failure: function (result, request) {
console.log('api call was a failure');
},
scope: this
});
}
});
Now of course your data won't have "displayname, gender" etc.. but you should get the point.
I also found a working example here (I find it very sad that Sencha allows broken demos on their own website): http://demo.rasc.ch/eds/touch23/grid/grid/index.html

Resources