How to load XML into a list using Sencha/Phonegap? - javascript

I'm trying to setup a native style app using sencha touch and phonegap. I'm trying to pull in data from an external XML feed into the model.
In my model (Event.js) I have this:
Ext.regModel('Event', {
fields: [
{name: 'title', type: 'string'}
]
});
In my store (eventsstore.js):
ToolbarDemo.eventstore = new Ext.data.Store({
model: 'Event',
sorters: 'title',
getGroupString : function(record) {
return record.get('title')[0];
},
proxy: {
type: 'ajax',
url: 'http://the-url-to-the-file.xml',
reader: {
type: 'xml',
root: 'events',
record: 'event'
}
},
autoLoad: true
});
And in the view (tried as a list):
ToolbarDemo.views.Eventscard = Ext.extend(Ext.List, {
title: "Events",
iconCls: "search",
store: ToolbarDemo.eventstore,
itemTpl: '{title}',
grouped: true,
indexBar: true,
cardSwitchAnimation: 'slide'
});
Ext.reg('eventscard', ToolbarDemo.views.Eventscard);
And tried as a panel:
ToolbarDemo.views.Eventscard = Ext.extend(Ext.Panel, {
title: "Events",
iconCls: "search",
dockedItems: [{
xtype: 'toolbar',
title: 'Events'
}],
layout: 'fit',
items: [{
xtype: 'list',
store: ToolbarDemo.eventstore,
itemTpl: '{title}',
grouped: true
}],
//This was an experiment, safe to leave out?
initComponent: function() {
//ToolbarDemo.eventstore.load();
ToolbarDemo.views.Eventscard.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('eventscard', ToolbarDemo.views.Eventscard);
Now when I navigate to that card view, the loading overlay/spinner is displayed but that's as far as it goes, the list of items does not appear. Any ideas of what I'm doing wrong?

I am not that much familier with this, I have used like this to display a list.. try this
ToolbarDemo.eventstore.load();
var itemTpl = new Ext.XTemplate('<div id='title'>{title}</div>');
this.eventStoreList = new Ext.List({
id: 'eventStoreList',
store: ToolbarDemo.eventstore,
itemTpl: itemTpl,
height: 370,
indexBar: false
});
this.eventStoreListContainer = new Ext.Container( {
id : 'eventStoreListContainer',
items : [this.eventStoreList]
});
this.items = [this.eventStoreListContainer];
ToolbarDemo.views.Eventscard.superclass.initComponent.apply(this);

Well, I got it working!
I added ToolbarDemo.eventstore.read(); to the end of my store code, saved the XML file locally in the root 'www' folder then using the list method worked fine!
Does any body know why this (calling a remote XML) could be a problem?
EDIT: Turns out that it works fine in the browser like that, but not the iPhone simulator. So now I've set it back to the remote URL and added the URLs to the PhoneGap Whitelist and it works great :)

Related

Problems with references and stores in Sencha ExtJS

I’m new here in at Stackoverflow and to Sencha ExtJS development. I’m a student from Germany and I’m current trying to get my degree in media computer sciences. As a part of my final assignment I’m currently developing the UI of a webapp for a local company.
While I was trying out the capabilities of the Sencha ExtJS framework I came across some problems, which is why I’m now reaching out to the community for help ;)
My first problem I had, was when I was playing around with the syntax for instancing classes using xtypes and the association of Stores inside the ViewModel:
For the purpose of easier to read and less cluttered code I wanted to give my stores their own xtype so I could instead of declaring all the stores and their configs inside the ViewModels’ stores config wanted to have every store inside their own file and then just create an instance of them later inside the ViewModel. The code I wrote for this looks like this:
ViewModel:
Ext.define('Example.viewmodel.MyViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myviewmodel',
requires: [
'Example.store.MyStore',
],
stores: {
StoreA: { xtype: 'store_a' },
StoreB: { xtype: 'store_b' },
StoreC: { xtype: 'store_c' }
},
data: {
/* This object holds the arbitrary data that populates the ViewModel and
is then available for binding. */
}
});
StoreA:
Ext.define('Example.store.StoreA', {
extend: 'Ext.data.Store',
xtype: 'store_a',
requires: [
'Example.model.ModelA'
],
storeId: 'StoreA',
autoLoad: false,
model: 'Example.model.ModelA',
listeners: {
load: 'onLoadofStoreA'
}
});
But apparently this isn’t working… My load listener of the store does not seem to fire at the method inside my controller and does not even seem to know about the view that is associated with the ViewModel. What am I doing wrong or is this just not meant to be done like that?
My Second Problem was when I was playing around with some of the UI components. My scenario was like this:
I wanted to have a menu that would slide in, where u could do some inputs that would then load the content for the view.
I found this example for a sliding menu (https://examples.sencha.com/extjs/6.7.0/examples/kitchensink/?modern#menus) and built this:
Inside my ViewController:
getMenuCfg: function (side) {
var cfg = {
side: side,
controller: example_controller',
id: 'topMenu',
items: [
{
xtype: 'container',
layout: 'hbox',
width: '100%',
items: [
{
xtype: 'fieldset',
reference: 'fldSet',
id: 'fldSet',
layout: 'vbox',
width: '50%',
defaults: {
labelTextAlign: 'left'
},
items: [
{
autoSelect: false,
xtype: 'selectfield',
label: 'Selectfield',
reference: 'sfExample',
id: 'sfExample',
listeners: {
change: 'onSFChange'
}
},
{
xtype: 'container',
layout: {
type: 'hbox',
align: 'end',
pack: 'center'
},
items: [{
xtype: 'textfield',
reference: 'ressource',
id: 'ressource',
flex: 1,
textAlign: 'left',
margin: '0 10 0 0',
label: 'Ressource',
labelAlign: 'top',
labelTextAlign: 'left',
editable: false,
readOnly: true
},
{
xtype: 'button',
shadow: 'true',
ui: 'action round',
height: '50%',
iconCls: 'x-fa fa-arrow-right',
handler: 'openDialog'
}
]
},
{
xtype: 'textfield',
reference: 'tfExample',
id: 'tfExample',
label: 'Textfield',
editable: false,
readOnly: true
}
]
},
}]
}];
The problem I come across now is, that I would no longer be able to easily get the references of components inside the menu (input fields) with this.lookupReference() as if they were just part of the view. In fact to find a workaround I had to trace a way back to the components using a debugger.
For example if another method inside my controller wanted to use a field inside this menu, instead of simply just doing this.lookupReference(‘sfExample’) I now had to do something like this:
var me = this,
vm = me.getViewModel(),
menuItems = me.topMenu.getActiveItem().getItems(),
fieldset = menuItems.getByKey('fldSet'),
selectfieldRessArt = fieldsetLeft.getItems().getByKey('sfExample');
I’m pretty sure that I am missing out on something important here and there has to be a way to do this easier. I’m really looking forward to your answers, thank you in advance ;)
use xtype only for components. if you need to define an type/alias for store, use alias config property instead and especify the alias category "store.".
Defining a store with an alias
Ext.define('Example.store.StoreA', {
extend: 'Ext.data.Store',
//use store. to category as a store
alias: 'store.store_a',
requires: [
'Example.model.ModelA'
],
storeId: 'StoreA',
autoLoad: false,
model: 'Example.model.ModelA',
listeners: {
load: 'onLoadofStoreA'
}
});
Instantianting your store by type
Ext.define('Example.viewmodel.MyViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myviewmodel',
requires: [
'Example.store.MyStore',
],
stores: {
StoreA: { type: 'store_a' },
StoreB: { type: 'store_b' },
StoreC: { type: 'store_c' }
},
data: {
/* This object holds the arbitrary data that populates the ViewModel and
is then available for binding. */
}
});
I Hope it can help you

JS console error shows Extjs trying to make a GET request for a class as if it was a file

Sorry if the title isn't the best.
I'm roughing out a test project in Extjs 6. I have a viewmodel class that uses a store called customers:
Ext.define('ChildSessionBinding.view.main.ChildSessionModel',{
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.binding.childsession',
requires:[
'Ext.data.Store',
'ChildSessionBinding.model.Customer'
],
stores:{
customers:{
model: 'ChildSessionBinding.model.Customer',
autoLoad: true,
session: true
}
}
});
The model it requires has hard coded test data in it:
Ext.define('ChildSessionBinding.model.Customer', {
extend: 'Ext.data.Model',
fields: [
{ name: 'name', type: 'auto' },
{ name: 'phone', type: 'auto' }
],
data:[
{name: 'test', phone: '12345'}
]
});
And the view that uses the ViewModel is just a panel that shows a simple grid:
Ext.define('ChildSessionBinding.view.main.ChildSession', {
extend: 'Ext.panel.Panel',
xtype: 'binding-child-session',
title: 'Binding Child Session Demo',
layout: {
type: 'vbox',
align: 'stretch'
},
viewModel: {
type: 'binding.childsession'
},
controller: 'binding.childsession',
session: true,
items:[
{
flex: 1,
xtype: 'grid',
bind: '{customers}',
columns:[
{
dataIndex: 'name',
flex: 1,
text: 'Name'
},
{
dataIndex: 'phone',
flex: 1,
text: 'Phone'
},
{
xtype: 'widgetcolumn',
width: 90,
widget: {
xtype: 'button',
text: 'Edit',
handler: 'onEditCustomerClick'
}
}
]
}
]
});
When I load this in the browser, the grid does not load. I popped open the javascript console and saw that it was trying to make a get request to the server using the model's fully qualified name:
I've compared it to the kitchen sink example I'm trying to duplicate as well as other viewmodel stores that I've created in other projects and I don't see anything that would cause this.
Also, to rule out any project file structure questions, here's the folder/file structure:
EDIT
Here's the stack trace from the javascript console:
Anyone see the problem?
Put the data in your store, not in your model. Model doesn't have a data property.
I haven't used much of Ext 5 or 6 but I think I have seen this error on Ext 4. If a required class is undefined during the time of a class definition Ext will try to load a file with that name at the root of your application. I think that Ext should be throwing an error here by default instead of trying to load a file since I assume that most applications are not set up to handle this.
The fix would be to have ChildSessionBinding.model.Customer defined and executed before you load ChildSessionBinding.view.main.ChildSessionModel or have your application be able to load that file where Ext expects it to be.

Sencha Touch List with Model and Store

I am looking for a tutorial / sourcecode for a sencha touch list with a model and a store. I am facing some issues with Sencha Touch 2.2.1.
Model:
Ext.define("DeviceAPIFramework.model.OfferModel", {
extend: "Ext.data.Model",
config: {
fields: [
{ name: "description", type: "string" },
{ name: "id", type: "string" }
]
}
});
Store:
Ext.define("DeviceAPIFramework.model.OfferStore", {
extend: "Ext.data.Store",
config: {
storeId: "offerStore",
model:'DeviceAPIFramework.model.OfferModel'
}
});
Controller:
offerStore.add({description: 'test', id: 'my id'});
Ext.ComponentQuery.query('#offersListHomeView')[0].update();
View:
Ext.require("DeviceAPIFramework.model.OfferStore");
var offerStore = Ext.create("DeviceAPIFramework.model.OfferStore");
Ext.define ...........
{
xtype: 'list',
width: Ext.os.deviceType == 'Phone' ? null : 1200,
height: Ext.os.deviceType == 'Phone' ? null : 350,
title: 'test',
itemId: 'offersListHomeView',
store: offerStore,
itemTpl: '{description} {id}'
}
Image:
After executing the code from the controller, a new row gets appended, but also a weird undefined text on the upper left corner of my list. Any suggestions how to fix this issue?
I also don't like the variable offerStore outside the view. If I put it in the controller, the view is nagging.
The undefined is coming from this line:
Ext.ComponentQuery.query('#offersListHomeView')[0].update();
update is decrapted(I wrote it, because I was developing once with an old Sencha Touch version and this update was necessary) and will call setHtml(), because we are passing no arguments it is settings "undefined", which will be shown in our view. In the new sencha version, you can simply delete this line.
I also managed the global store problem with this code in the controller:
launch: function() {
this.offersStore = Ext.create('Ext.data.Store', {
model: 'DeviceAPIFramework.model.OfferModel'
});
Ext.ComponentQuery.query('#offersListHomeView')[0].setStore(this.offersStore);
},

ExtJS 4.1 Infinite Grid Scrolling doesnt work with Dynamic store using loadData

I have to load first grid panel on tab and then load data into store using loadData() function which is working fine, but now I have to integrate infinite grid scrolling with it.
Is there any way to integrate infinite scrolling on fly after loadData into store..? I am using ExtJS 4.1. Please help me out.
Here I am showing my current script in controller and grip view panel in which I have tried out but not working.
Controller Script as below:
var c = this.getApplication().getController('Main'),
data = c.generateReportGridConfiguration(response,true),
tabParams = {
title: 'Generated Report',
closable: true,
iconCls: 'view',
widget: 'generatedReportGrid',
layout: 'fit',
gridConfig: data
},
generatedReportGrid = this.addTab(tabParams);
generatedReportGrid.getStore().loadData(data.data);
On Above script, once I get Ajax call response, adding grid panel with tabParams and passed data with gridConfig param which will be set fields and columns for grid and then last statement supply grid data to grid. I have tried out grid panel settings by following reference example:
http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/infinite-scroll.html
On above page, Included script => http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/infinite-scroll.js
My Grid Panel Script as below:
Ext.define('ReportsBuilder.view.GeneratedReportGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.generatedReportGrid',
requires: [
'ReportsBuilder.view.GenerateViewToolbar',
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.grid.PagingScroller',
'Ext.grid.RowNumberer',
],
initComponent: function() {
Ext.define('Report', {extend: 'Ext.data.Model', fields: this.gridConfig.fields, idProperty: 'rowid'});
var myStore = Ext.create('Ext.data.Store', {model: 'Report', groupField: 'name',
// allow the grid to interact with the paging scroller by buffering
buffered: true,
pageSize: 100,
autoSync: true,
extraParams: { total: 50000 },
purgePageCount: 0,
proxy: {
type: 'ajax',
data: {},
extraParams: {
total: 50000
},
reader: {
root: 'data',
totalProperty: 'totalCount'
},
// sends single sort as multi parameter
simpleSortMode: true
}
});
Ext.apply(this, {
dockedItems: [
{xtype: 'generateviewToolbar'}
],
store: myStore,
width:700,
height:500,
scroll: 'vertical',
loadMask: true,
verticalScroller:'paginggridscroller',
invalidateScrollerOnRefresh: false,
viewConfig: {
trackOver: false,
emptyText: [
'<div class="empty-workspace-bg">',
'<div class="empty-workspace-vertical-block-message">There are no results for provided conditions</div>',
'<div class="empty-workspace-vertical-block-message-helper"></div>',
'</div>'
].join('')
},
columns: this.gridConfig.columns,
features: [
{ftype: 'groupingsummary', groupHeaderTpl: '{name} ({rows.length} Record{[values.rows.length > 1 ? "s" : ""]})', enableGroupingMenu: false}
],
renderTo: Ext.getBody()
});
// trigger the data store load
myStore.guaranteeRange(0, 99);
this.callParent(arguments);
}
});
I have also handled start and limit from server side query but it will not sending ajax request on scroll just fired at once because pageSize property in grid is 100 and guaranteeRange function call params are 0,99 if i will increased 0,299 then it will be fired three ajax call at once (0,100), (100,200) and (200,300) but showing data on grid for first ajax call only and not fired on vertical scrolling.
As, I am new learner on ExtJs, so please help me out...
Thanks a lot..in advanced.
You cannot call store.loadData with a remote/buffered store and grid implementation and expect the grid to reflect this new data.
Instead, you must call store.load.
Example 1, buffered store using store.load
This example shows the store.on("load") event firing.
http://codepen.io/anon/pen/XJeNQe?editors=001
;(function(Ext) {
Ext.onReady(function() {
console.log("Ext.onReady")
var store = Ext.create("Ext.data.Store", {
fields: ["id", "name"]
,buffered: true
,pageSize: 100
,proxy: {
type: 'rest'
,url: '/anon/pen/azLBeY.js'
reader: {
type: 'json'
}
}
})
store.on("load", function(component, records) {
console.log("store.load")
console.log("records:")
console.log(records)
})
var grid = new Ext.create("Ext.grid.Panel", {
requires: ['Ext.grid.plugin.BufferedRenderer']
,plugins: {
ptype: 'bufferedrenderer'
}
,title: "people"
,height: 200
,loadMask: true
,store: store
,columns: [
{text: "id", dataIndex: "id"}
,{text: "name", dataIndex: "name"}
]
})
grid.on("afterrender", function(component) {
console.log("grid.afterrender")
})
grid.render(Ext.getBody())
store.load()
})
})(Ext)
Example 2, static store using store.loadData
You can see from this example that the store.on("load") event never fires.
http://codepen.io/anon/pen/XJeNQe?editors=001
;(function(Ext) {
Ext.onReady(function() {
console.log("Ext.onReady")
var store = Ext.create("Ext.data.Store", {
fields: ["id", "name"]
,proxy: {
type: 'rest'
,reader: {
type: 'json'
}
}
})
store.on("load", function(component, records) {
console.log("store.load")
console.log("records:")
console.log(records)
})
var grid = new Ext.create("Ext.grid.Panel", {
title: "people"
,height: 200
,store: store
,loadMask: true
,columns: [
{text: "id", dataIndex: "id"}
,{text: "name", dataIndex: "name"}
]
})
grid.on("afterrender", function(component) {
console.log("grid.afterrender")
})
grid.render(Ext.getBody())
var data = [
{'id': 1, 'name': 'Vinnie'}
,{'id': 2, 'name': 'Johna'}
,{'id': 3, 'name': 'Jere'}
,{'id': 4, 'name': 'Magdalena'}
,{'id': 5, 'name': 'Euna'}
,{'id': 6, 'name': 'Mikki'}
,{'id': 7, 'name': 'Obdulia'}
,{'id': 8, 'name': 'Elvina'}
,{'id': 9, 'name': 'Dick'}
,{'id': 10, 'name': 'Beverly'}
]
store.loadData(data)
})
})(Ext)

Populate ExtJS combobox with JSON

I am using ExtJS (3) and just trying to populate a combobox/drop down using records from the database that are being queried using JSON.
Here is my JSON call:
var projectDropDown = new Ext.data.Store({
autoLoad: true,
url: 'dropdown.json',
storeId: 'projectDropDown',
idProperty: 'ProjectID',
fields: [ 'ProjectID', 'ProjectName' ]
});
And then my combobox code:
{
xtype: 'combo',
id: 'ProjectName',
fieldLabel: 'Project Name',
valueField: 'ProjectID',
displayField: 'ProjectName',
store: projectDropDown,
typeAhead: true,
mode: 'local',
triggerAction: 'all',
emptyText:'Select a Project...',
selectOnFocus:true
}
The JSON is returning my data like this:
[
{
"ProjectID":"1",
"ProjectName":"Mike's Test Project"
},
{
"ProjectID":"2",
"ProjectName":"My Second Test Project"
},
{
"ProjectID":"3",
"ProjectName":"My Third Project"
},
{
"ProjectID":"6",
"ProjectName":"More testing from me"
}
]
I think I am close, I just don't see what I am missing to make the connection.
Thanks for any assistance.
The first step I would do would be to output the store (or size of the store or something) to the console to see if the data is getting loaded properly into the store.
My guess would be that you need to enclose your JSON that is returned into some root object. Try giving your store a JSONReader with a root element specified like so:
var projectDropDown = new Ext.data.Store({
autoLoad: true,
url: 'dropdown.json',
storeId: 'projectDropDown',
reader: new Ext.data.JsonReader(
{
root: 'projects'
}),
idProperty: 'ProjectID',
fields: [ 'ProjectID', 'ProjectName' ]
});
Then change the JSON returned to look like this instead
{
"projects" : [
{"ProjectID":"1","ProjectName":"Mike's Test Project"},
{"ProjectID":"2","ProjectName":"My Second Test Project"},
....
]
}

Categories

Resources