I just discovered even my simplest 2.0 app fails with IE. This works fine with 2.0 or 2.0p2, but in IE it fails with SCRIPT5007: Unable to get value of the property 'length': object is null or undefined sdk-debug.js, line 43756 character 13
This happens on at least one of my other scripts as well. I'm using IE9.09, and running in debug mode outside of Rally.
Ext.define('FieldEscalations', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
Rally.data.ModelFactory.getModel({
type: 'Defect',
success: function(model) {
this.grid = this.add({
xtype: 'rallygrid',
model: model,
disableColumnMenus: false,
columnCfgs: [
'FormattedID',
'Tags'
],
storeConfig: {
filters: [
{
property: 'State',
operator: '<',
value: 'Closed'
}, {
property: 'SupportTicket',
operator: '!=',
value: ''
}
],
sorters: [
{
property: 'CreationDate',
direction: 'DESC'
}
]
}
});
},
scope: this
});
}
});
This fails due to the fact that IE9 does not support local storage when running from the file system:
local storage in IE9 fails when the website is accessed directly from the file system
I will file a defect on this. Your app should work when running inside a custom html panel on a dashboard in Rally, right?
Related
I have a piece of code in a Sencha Touch v2 controller as shown below. When this code is ran the count after the store.add is (6), the counter after the store.sync is (0) and the store.sync is succeeding.
NOTE: items holds 6 records received from a JsonP proxy, no errors are shown in the console and everything acts as though it was a full success.
requires: [
'Ext.data.proxy.JsonP',
'Ext.data.proxy.Sql'
],
config: {
models: ['Convention'],
stores: ['Conventions']
},
// ***additional code*** //
store.setProxy({
type: 'sql',
database: 'app',
table: 'Conventions'
});
store.removeAll();
store.sync({
success: function(batch){
store.add(items);
console.log("Count before: " + store.getCount()); << Shows (6)
store.sync({
failure: function (batch, options) {
console.log('Convention Sql failure');
},
success: function(batch,options){
console.log("Count after: " + store.getCount()); << Shows (0)
console.log("Convention Sql success");
store.load();
Ext.Viewport.unmask();
}
});
}
});
The model is show here
extend: 'Ext.data.Model',
config: {
idProperty: 'id',
fields: [
{ name: 'id', type: 'string' },
{ name: 'name', type: 'string' },
{ name: 'logoId', type: 'string' },
{ name: 'seasonId', type: 'string'},
{ name: 'viewed', type: 'string'},
{ name: 'dateCreated', type: 'string'},
{ name: 'dateUpdated', type: 'string'}
]
}
and the store is here
extend: 'Ext.data.Store',
requires: [
'Ext.data.proxy.Sql'
],
config: {
model: 'app.model.Convention',
autoLoad: false,
sorters:[{
property: 'name',
direction: 'ASC'
}],
proxy: {
type: 'sql',
database: 'app',
table: 'Conventions'
}
}
After much research it seems that Sencha recently changed some of their code on how they handle IDs. As such, if you are using code examples previous to this change you will get errors when you try to save to the ID field.
Sencha has added the clientIdProperty that you can add to the writer of a proxy and directly to the model.
Reference: http://docs.sencha.com/touch/2.4/2.4.2-apidocs/#!/api/Ext.data.Model-cfg-clientIdProperty
The name of a property that is used for submitting this Model's unique client-side identifier to the server when multiple phantom records are saved as part of the same Operation. In such a case, the server response should include the client id for each record so that the server response data can be used to update the client-side records if necessary. This property cannot have the same name as any of this Model's fields.
As such, my code above will have the following changes to the following where 'siteId' is my id being passed from the Json request and the ID on my server for the record.
model
idProperty: 'id',
clientIdProperty: 'siteId',
identifier: 'uuid',
Controller
store.setProxy({
type: 'sql',
database: 'app',
table: 'Conventions',
writer: {
clientIdProperty: 'siteId'
}
});
I'm currently working with comboboxes and filters to implement an option to select all instances of a desired field. With that said, I know to use the noEntryText attribute to set what originally defaults to "--No Entry--" as "All". However, the changes do not seem to apply when I use this on custom fields provided by my Web Services API (those fields with the "c_" before them).
Strangely enough though, this convention works for other fields that I use that do not have the "c_" before them. So is this a known defect just for custom fields or is there a workaround to this issue?
I filed a defect that replacing noEntryText to a custom value works for rallyfieldvaluecombobox for standard fields, but not custom fields.
If rallyfieldvaluecombobox uses a standard field, e.g. Environment, then no entry can be replaced successfully:
Here is the js file:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
this.add({
xtype: 'rallyfieldvaluecombobox',
itemId: 'aBox',
fieldLabel: 'Filter by filed:',
model: 'defect',
//field: 'c_CustomBox',
field: 'Environment',
noEntryText: 'All',
useNullForNoEntryValue: true,
allowNoEntry: true,
listeners: {
select: this._onSelect,
ready: this._onLoad,
scope: this
}
});
},
_onLoad: function() {
this.add({
xtype: 'rallygrid',
columnCfgs: [
'FormattedID',
'Name',
//'c_CustomBox'
'Environment'
],
context: this.getContext(),
storeConfig: {
model: 'defect',
filters: [this._getStateFilter()]
},
width: 500
});
},
_getStateFilter: function() {
if (!this.down('#aBox').getValue()) {
return 1;
}
else{
return {
//property: 'c_CustomBox',
property: 'Environment',
operator: '=',
value: this.down('#aBox').getValue()
};
}
},
_onSelect: function() {
var grid = this.down('rallygrid'),
store = grid.getStore();
store.clearFilter(true);
store.filter(this._getStateFilter());
}
});
If the same rallyfieldvaluecombobox uses a custom field, then no entry string cannot be replaced:
In both cases the functionality of replacing the filtering behavior works fine.
I am new for this platform, Now i am unable to set dyanimic url using category id and token.
What i want:
I have list different items, which have different ids but same token, token(tokent is same one user) getting from login phase. I want to get value accorading to category id from the server.
Here is the my model:
Ext.define('MyApp.model.CategoryDisplayModelMenu', {
extend: 'Ext.data.Model',
config: {
fields: [
/*'cat_id',*/
'category',
'name',
],
belongsTo: "MyApp.model.CategoryDisplayModel"
}
});
and another related model is:
Ext.define('MyApp.model.CategoryDisplayModel', {
extend: 'Ext.data.Model',
requires: ['MyApp.model.CategoryDisplayModelMenu'],
config: {
fields: [
{name:'data', mapping: 'data'},
{name:'name'},
{name: 'category'},
{name: 'author'},
],
}
});
What i am set in store, but could not work:
Ext.define('MyApp.store.CategoryValueStore', {
extend: 'Ext.data.Store',
alias: 'store.CategoryValueStore',
requires: [
'MyApp.model.CategoryDisplayModel'
],
config: {
model: 'MyApp.model.CategoryDisplayModel',
storeId: 'categoriesvaluestore',
proxy: {
type: 'rest',
url: 'http://horror/myapp/api/word/searched_words/catID/'+ 1+'/'+ SDSILLYTOKEN+'/'+650773253e7f157a93c53d47a866204dedc7c363,
noCache: false,
reader: {
type: 'json',
rootProperty: ''
} } }
});
How to set above url, dynamic, cat id and token may be differnt.
But it works when i set these in store
Ext.define('MyApp.store.ArchitectureDisplayStore',{
extend: 'Ext.data.Store',
requires:[
'MyApp.view.Main'
],
config:
{
model: 'MyApp.model.CategoryDisplayModel',
autoLoad:true,
id:'Category',
proxy:
{
type: 'ajax',
url : 'http://horror/myapp/api/word/searched_words/catID/1/SDSILLYTOKEN/650773253e7f157a93c53d47a866204dedc7c363', // file containing json data
reader:
{
rootProperty:''
} } }
});
In View , I set getting value on list like this:
Ext.define("MyApp.view.ArchitectureDisplayMain", {
extend: 'Ext.Container',
alias: "widget.architecturewords",
config: {
{
xtype: 'list',
scrollable: true,
itemId: 'demolist',
itemTpl: [
'<div><tpl for="data"><ul class="catList">{name} -test- {category}</ul> <ul>{author}</ul></tpl></div>'
],
store: 'categoriesvaluestore',
}
}
});
My category display model:
Ext.define('MyApp.model.CategoryModelMenu', {
extend: 'Ext.data.Model',
config: {
fields: [
'cat_id',
'category_name',
],
belongsTo: "MyApp.model.CategoryModel"
}
});
and
Ext.define('MyApp.model.CategoryModel', {
extend: 'Ext.data.Model',
requires: ['MyApp.model.CategoryModelMenu'],
config: {
fields: [
{name:'data', mapping: 'data'},
{name: 'cat_id'},
{name: 'category_name'},
],
}
});
EDIT:
Ext.define('MyApp.view.Category', {
extend: 'Ext.List',
alias: "widget.category",
config: {
title: 'Stores',
cls: 'category-data',
scrollable: false,
store: 'CategoryStore',
itemTpl: [
'<div class="categoryListings">',
'<tpl for="data">',
'<span onClick="catOption({cat_id})">{category_name}</span> ',
'</tpl>',
'</div>',
].join('')
}
//}
});
function catOption(id){
console.log("ID--"+id);
var tokan= '650773253e7f157a93c53d47a866204dedc7c363';
Ext.Viewport.remove(Ext.Viewport.getActiveItem(), true);
Ext.Viewport.add([
{ xtype: 'wordsview' }
]);
} and others
In wordsview, I like to display respective words of clicked category.
It is ok, when click this, first item of id p1, it shows next view.
Please tell me, How to get dynamic data accorading to its category id and token. please give some solution.Thank you advance.
If i understood you correctly
Let's say if you have category id and token in localStorage.
You can do like this
proxy:
{
type: 'ajax',
url : 'http://horror/myapp/api/word/searched_words/catID/'+localStorage.catId+'/SDSILLYTOKEN/'+localStorage.token,
reader:{
rootProperty:''
}
}
OR
Do as #Alex posted. That is better way.. Like
function catOption(id){
console.log("ID--"+id);
var token= '650773253e7f157a93c53d47a866204dedc7c363';
var url = 'http://horror/myapp/api/word/searched_words/catID/'+id+'/SDSILLYTOKEN/'+token;
Ext.getStore("categoriesvaluestore").getProxy().setUrl(url);
Ext.getStore("categoriesvaluestore").load();
Ext.Viewport.remove(Ext.Viewport.getActiveItem(), true);
Ext.Viewport.add({ xtype: 'wordsview' });
}
When accessing your Store from your View or anywhere else, you can dinamically change the Url this way:
var stProxy = Ext.StoreMgr.get("myStore").getProxy();
stProxy.setUrl("http://the.new.url");
Ext.StoreMgr.set("myStore").setProxy(stProxy);
--
The particular problem in your scenario is that you may have to populate your list manually. If you want a List to include the result of calling the same Store with different URLs, I suggest to build a new local Store loading the content of all iterations. Then make the List "store" property be this global Store.
Using the 2.0p4 JavaScript SDK, I am trying to recreate a grid app I created previously using 1.30 JavaScript SDK, and am having problems creating a complex filter (with multiple ANDs and ORs).
Here is the query from the 1.30 version:
function itemQuery() {
var queryObject = {
key: 'defect',
type: 'defect',
fetch: 'FormattedID,Name,State,ScheduleState,SupportNumber,OpenedDate,Priority,Rank,Severity,SubmittedBy,Owner,Iteration,Release,Project',
query: '(((((SupportNumber contains "RNT") OR (SupportNumber contains "NS")) OR (SupportNumber contains ":")) OR (SupportNumber contains "CASE")) AND (State != Closed))',
project: null
};
So I querying for items that contains "RNT", ":", "NS", or "CASE" AND are not closed.
(SupportNumber is a custom field, which people have entered data in differently at different points)
And here is my App.js from the new version I am trying to create:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
Rally.data.ModelFactory.getModel({
type: 'Defect',
context: {
workspace: 'workspace/12345',
project: null,
},
success: function(model) {
this.grid = this.add({
xtype: 'rallygrid',
model: model,
columnCfgs: [
'FormattedID',
'Name',
'SupportNumber',
'Priority',
'Severity',
'State',
'Iteration',
'Release',
'Project',
'Owner',
'SubmittedBy'
],
storeConfig: {
filters: [
{
property: 'State',
operator: '!=',
value: 'Closed'
},
{
property: 'SupportNumber',
operator: 'contains',
value: 'RNT'
}
]
}
});
},
scope: this
});
}
});
I can see that just by adding filters to the config, you create ANDs, however I am lost in the documentation with how to create ANDs and ORs filters in the same config.....
Any direction anyone can give on how to create filter configs for App SDK 2.0, that use multiple ANDs and ORs, would be greatly appreciated.
Check out:
Rally.data.QueryFilter
Along with this Stackoverflow Answer:
Rally App SDK 2.0: Cannot modify QueryFilter object after initial creation
Which shows a nice example of using Rally.data.QueryFilter to prepare an array of filters representing multiple conditions.
I have two lists in 2 separate tabs, both hooked up to a server side database. I'm attempting to set up list paging and on one of the lists its functioning exactly as it should be. For the other list, the model and store have all the same settings as the list that pages properly but no 'Load More..." text shows up at the bottom for this list.
With regards to the list paging plugin, both lists are basically exactly the same as each other (ie the Store, Model, 'List' view) but on one the paging just does not work. Does anyone have any idea what could possibly be causing this?
Editing with some more information:
I'm using Chrome to develop. Looking at the Network I seem to be getting JSON that looks right, for the one thats not working it's returning 8 records, and the total property returned is 13 (this makes sense because I've got my page size set to 8).
The Store from list that does NOT work
Ext.define("IdeaBank.store.SharedProblems", {
extend: "Ext.data.Store",
required: "IdeaBank.model.SharedProblem",
config: {
model: "IdeaBank.model.SharedProblem",
clearOnPageLoad: false,
pageSize: 8,
proxy: {
type: 'ajax',
api: {
create: "http://mywebsite.com/submitProblem.php?action=create",
read: "http://mywebsite.com/submitProblem.php?action=read",
update: "http://mywebsite.com/submitProblem.php?action=update",
destroy: "http://mywebsite.com/submitProblem.php?action=delete",
},
reader: {
type: 'json',
rootProperty: "problems",
totalProperty: "total",
}
},
autoLoad: true
}
});
The Store from list that does work
Ext.define("IdeaBank.store.SharedSolutions", {
extend: "Ext.data.Store",
required: "IdeaBank.model.SharedSolution",
config: {
model: "IdeaBank.model.SharedSolution",
clearOnPageLoad: false,
proxy: {
type: 'ajax',
api: {
create: "http://mywebsite.com/submitSolution.php?action=create",
read: "http://mywebsite.com/submitSolution.php?action=read",
update: "http://mywebsite.com/submitSolution.php?action=update",
destroy: "http://mywebsite.com/submitSolution.php?action=delete",
},
reader: {
type: 'json',
rootProperty: "solutions",
totalProperty: "total",
}
},
pageSize: 8,
autoLoad: true
}
});
List view from the one that does NOT work
Ext.define("IdeaBank.view.SharedProblemsList", {
extend: 'Ext.dataview.List',
alias: 'widget.sharedproblemslist',
requires: ['Ext.plugin.ListPaging'],
config: {
autoLoad: true,
plugins: [
{
xclass: 'Ext.plugin.ListPaging',
autoPaging: true
}
],
loadingText: "Loading...",
emptyText: [
"</pre><div class='notes-list-empty-text' style = 'padding: 2em;'>",
"<p>There are no problems listed for the category you have selected.</p>",
"</div><pre>"
].join(""),
onItemDisclosure: true,
itemTpl: [
"</pre>",
"<div class = 'list-item-title'><span style = 'margin-right: 5px; color: #25E014; font-size: 0.7em;'>{rating}</span> {problem}</div>",
"<pre>"
].join(""),
}
});
List view from the one that does work
Ext.define("IdeaBank.view.SharedSolutionsList", {
extend: 'Ext.dataview.List',
alias: 'widget.sharedsolutionslist',
requires: ['Ext.plugin.ListPaging'],
config: {
autoLoad: true,
plugins: [
{
xclass: 'Ext.plugin.ListPaging',
autoPaging: true
}
],
loadingText: "Loading...",
emptyText: [
"</pre><div class='notes-list-empty-text' style = 'padding: 2em;'>",
"<p>There are no published solutions for the category you have selected.<p>",
"</div><pre>"
].join(""),
onItemDisclosure: true,
itemTpl: [
"</pre>",
"<div class = 'list-item-title'><span style = 'margin-right: 5px; color: #25E014; font-size: 0.7em;'>{rating}</span> {title}</div>",
"<pre>"
].join(""),
}
});
Make sure that you implement the paging logic in your server side codes. You have to supply the functionality of sending page by page. Maybe "submitSolution.php" does not send the data partially.