Debugging some Sencha Touch 2 code and I've boiled it down to this. Why doesn't this work? More importantly, why shouldn't it? Clearly view, listOne, and listTwo are all in scope, but tapping listOne item, then going back, then tapping listOne item a second time results in an error. Does Navigation View delete references when it goes back?
var view = Ext.create('Ext.NavigationView', {
xtype:'myview',
fullscreen: true
});
var listTwo = Ext.create('Ext.List', {
store: {
fields: ['name'],
data: [
{name: 'Doeth'},
{name: 'Smith'},
{name: 'Johnson'},
{name: 'Stevens'}
]
},
itemTpl: '{name}'
});
var listOne = Ext.create('Ext.List', {
store: {
fields: ['name'],
data: [
{name: 'Cowper'},
{name: 'Everett'},
{name: 'University'},
{name: 'Forest'}
]
},
itemTpl: '{name}',
listeners: {
itemtap: function (me, index, target, record, e, eOpts ){
view.push(listTwo);
}
}
});
Ext.Viewport.add(view);
view.push(listOne);
Took a look at Sencha's source code and I confirm this is expected behaviour:
Ext.NavigationView, upon pressing back button calls its pop() method.
This, in turn, calls remove() on the NavigationView with the active view as argument. remove() is inherited from Ext.Container, and can optionally destroy the object. By default autoDestroy config is true, and this explains what's happening.
Set autoDestroy to false on the Navigation View to fix the error.
Sencha fiddle
Navigation View
Container
Related
I can't figure out why my data won't load to my AccordionList element from here:
https://github.com/kawanoshinobu/Ext.ux.AccordionList
I'm creating it within a panel like so:
{
xtype: 'accordionlist',
store: Ext.create('Rks.store.Bcks'),
flex: 1
},
It calls a store which is defined like so:
Ext.define('Rks.store.Bcks', {
extend: 'Ext.data.TreeStore',
requires: ['Rks.model.Bck'],
config: {
itemId: 'bks',
model: 'Rks.model.Bck',
defaultRootProperty: 'items',
proxy: {
type: 'ajax',
url: 'path/to/ajax',
},
autoLoad: false,
listeners:{
load: function( me, records, successful, operation, eOpts ){
console.log("data loaded", records);
}
}
}
});
When I call the view which contains the accordion, the console logs what appears to be a good object:
items: [{bck_id:3, author_id:1, title:test, items:[{c_id:2, bck_id:3, title:choice1, leaf:true}]}]
But nothing shows up. The panel is empty and no accordion items show.
However, when I replace the proxy with inline JSON, everything looks fine:
Ext.define('Rks.store.Bcks', {
extend: 'Ext.data.TreeStore',
requires: ['Rks.model.Bck'],
config: {
itemId: 'bks',
model: 'Rks.model.Bck',
defaultRootProperty: 'items',
root: {
items: [
{ bck_id: 1, author_id: 1, title: 'bck1', items: [ {c_id: 1, bck_id: 1, title: 'choice1', leaf: true} ] }
]
}
autoLoad: false,
listeners:{
load: function( me, records, successful, operation, eOpts ){
console.log("data loaded", records);
}
}
}
});
Here the items show up in the accordion. I can't figure out why the second example works and the first doesn't. Is there something special I should be doing when calling the store proxy for Accordion?
UPDATE: I have managed to get the accordion list to display data, but when I change the url of the store and reload it, the store reloads but the accordion list does not update. The accordion list continues to display the data it receives from the first URL, not from reloads with modified URLS.
Thanks
I think I figured this out. For the accordionlist component, you need to do like so:
var accordionlist = Ext.ComponentQuery.query('rdb #rdb1')[0];
var brickstore = Ext.getStore('bcs');
bcs.removeAll();
bcs.getProxy().setUrl('newurl');
accordionlist.setStore(bcs);
accordionlist.load();
basically, manually remove all items, set the new url, set the store on the list, then load the list.
I think there was a problem with your proxy configuration. First, remove the defaultRootProperty config (which is out of proxy config), then try this:
proxy: {
type: 'ajax',
url: (your ajax url),
reader: {
type: 'json',
rootProperty: 'items'
}
},
I want to use value from controller to filter store.I put this code:
My Controller:
showCatQuery: function(list,index,element,record){
var catid = record.get('id'); << Value to pass
this.getNavigation().push({
xtype: 'panel',
title: 'A',
scrollable: true,
styleHtmlContent: true,
catid: catid,
layout: {
type: 'fit'
},
items: [
{
xtype: 'showSearchCategory',
}
]
});
}
My view in initialize
this.callParent(arguments);
var sto = Ext.getStore('allapp');
sto.clearFilter();
sto.filter('categoryid', this.getCatid());
And this Error message:
Uncaught TypeError: Object [object Object] has no method 'getCatid'
Have you made sure, your View has a function called getCadid? This is what the error message is trying to tell you. You would have to make sure there is a method available while initializing.
Another, possible simpler approach is to filter the store in the controller - which would be the better approach from my perspective. The View would be able to just care about how anything is displayed and the controller cares about what data to display.
You can use references and controls to wait for the view to finish loading and then filter the store (or wait for the user to activate custom filters, etc.):
Ext.define('myApp.controller.aController', {
extend: 'Ext.app.Controller',
config: {
refs: {
justAName: 'ViewName'
}
control: {
justAName: {
activate: 'onActivateView'
}
}
}
onActivateView: function () {...}
});
This is the basic stub for a controller listening to the activation of a specific view. You can just get your store in this function and filter it by all data available in the controller. To get data from the View, create a reference to it, and access it in the controller via for example:
var data = this.getJustAnotherName().getValue();
//having a reference to a textfield for example called justAnotherName
I`m trying to write editable list with sencha touch,
I saw many examples but nothing did not work properly so I decided to build from scratch,
I have a list with items and on item tap my controller run the next code
showDetail: function (list, record) {
this.getMain().push({
xtype: 'vedit',
title: record.fullDetails(),
data: record.getData()
});
My "vEdit" screen is an form that should display the current tapped item data
This is the code for the edit form:
var form = Ext.define('TM.view.vEdit', {
extend: 'Ext.form.Panel',
xtype: 'vedit',
config: {
title: 'Edit task',
styleHtmlContent: true,
scrollable: 'vertical',
items: [
{
xtype: 'textfield',
name: 'title',
label: ''
},
{
xtype: 'textfield',
name: 'desc',
label: ''
}
]
}
});
I tried to load the data with the next code:
var ed = Ext.create('TM.model.mTasks', {
title: 'Ed',
desc: 'ed#sencha.com'
});
form.setRecord(ed);
and getting the next error:
Uncaught TypeError: Object function () {
return this.constructor.apply(this, arguments);
} has no method 'setRecord'
NEED YOUR HELP,
Thanks!
Since you have not define a field named record in form's config, so you won't get setRecord() method.
To pass on data you may try doing this:
form.config.record = ed;
and in initialize function of view you can get it like:
var taskData = this.config.record;
var form = Ext.define('TM.view.vEdit', {
Man, you need to create new form(), because it's just a type definition.
Given a simple Ext.List like the one in the Sencha docs, how can I make a new Panel or Carousel get "pushed" onto the screen when I click on one of the names?
http://docs.sencha.com/touch/2-0/#!/guide/list
I'd like to be able to have a button to navigate back to the main screen too.
You can achieve this using Ext.navigation.View. Here is a very simple application demonstrating this:
Ext.setup({
// onReady is when we can start building our application
onReady: function() {
// Create the view by just adding a config block into Ext.Viewport.
// We give it a reference of `view` so we can use it later
var view = Ext.Viewport.add({
// Give it an xtype of `navigationview` so it knows to create a NavigaitonView
xtype: 'navigationview',
// Define the list as its only item
items: [
{
xtype: 'list',
// Give it a title so the navigation view will show it
title: 'List',
// `itemTpl` is the template for each item in the list. We are going to create a store
// with a bunch of records, which each have a field called `name`, so we use that in our
// template
itemTpl: '{name}',
// Define our store
store: {
// Define the fields that our store will have
fields: ['name'],
// And give it some data for each record.
data: [
{ name: 'one' },
{ name: 'two' },
{ name: 'three' }
]
},
// Now we add a listener for the `itemtap` event, which is fired when a user taps on an item
// in this list. This event is passed various arguments in the signature, but we only need the
// record
listeners: {
itemtap: function(list, index, target, record) {
// now we have the record from the store, which was tapped. we now want to push a new view into
// the navigaitonview
view.push({
// Give it an xtype of panel
xtype: 'panel',
// Set the title to the name field of the record
title: record.get('name'),
// And add some random html
html: 'This is my pushed view!'
})
}
}
}
]
});
}
});
I've added inline comments so you know what is going on.
I also suggest you to ask questions over on the Sencha Forums as you will probably receive a much quicker response.
Here, i'm registering my app:
App = new Ext.Application({
name: "App",
launch: function() {
this.views.viewport = new this.views.Viewport();
}
});
This is the way i register new panels and components. I put each of them into seperate js files.
App.views.Viewport = Ext.extend(Ext.TabPanel, {
fullscreen: true,
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
items: [
{
xtype: 'cPanel'
},
{
xtype: 'anotherPanel'
}
]
});
// register this new extended type
Ext.reg('App.views.viewport', App.views.Viewport);
I added the other components in the same manner.
In one my components which is a list view, I want to change the container panel's activeItem with another panel when tappen on an item, like this: ( Viewport contains this container panel)
App.views.ListApp = Ext.extend(Ext.List, {
store: App.store,
itemTpl: "...",
onItemDisclosure: function(record) {
App.detailPanel.update(record.data);
App.cPanel.setActiveItem("detailPanel");
},
listeners: {
itemtap: function(view, index, item, e) {
var rec = view.getStore().getAt(index);
App.views.detailPanel.update(rec.data);
App.views.cPanel.setActiveItem("detailPanel", {type:"slide", direction: "left"});
}
}
});
App.views.detailPanel.update(rec.data);
But it says: can't call method "update" of undefined
I tried different variations on that line, like:
App.detailPanel.update(rec.data);
and i tried to give detailPanel and cPanel ids, where they were added to their container panel, and tried to reach them with Ext.get(), but none of these worked.
What is the problem here?
And any other advices would be appreciated.
Thanks.
The lazy way: give the panels ids and use:
Ext.getCmp(id)
The recommended way: Assign itemId to your panel and use:
App.views.viewport.getComponent(itemId)
This will allow you to have more than one instance of the same component at aby given time, the first example is not valid cause you can only have a singular id in the DOM tree.
Also getComponent only works for components stored in the items collection.