Sencha Touch 2 - Pass value to view from controller is Error? - sencha-touch-2

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

Related

How can I get a view in Sencha Touch 2 from within a controller by calling a function automatically generated by the ref config?

I have defined a controller in Sencha, that includes a refs attribute referencing my view, yet whenever I call the automatically generated "get" function to get the view, based on the refs attribute, it returns undefined. Here is my example:
I have the following controller in app/controller/Locals.js:
Ext.define('MobileUnion.controller.Locals', {
extend: 'Ext.app.Controller',
// Base class methods.
launch: function () {
this.callParent(arguments);
},
init: function () {
this.callParent(arguments);
},
config: {
refs: {
localsEditorView: 'localseditorview',
},
control: {
localsEditorView: {}
}
},
slideUpTransition: { type: 'cover', direction: 'up' },
onEditLocalsCommand: function() {
this.activateLocalsEditor();
},
activateLocalsEditor: function() {
var localsEditorView = this.getLocalsEditorView();
console.log(localsEditorView); // Returns "undefined" to console.
Ext.Viewport.animateActiveItem(localsEditorView, this.slideUpTransition);
}
});
I have the following view in app/views/LocalsEditor.js:
Ext.define('MobileUnion.view.LocalsEditor', {
extend: 'Ext.Panel',
alias: 'widget.localseditorview',
config: {
html: 'This is the new view which should show up on top!'
},
});
So, in the above example, if I call this.getLocalsEditorView() from within my controller, I get "undefined" even though I set a refs attribute as localsEditorView: 'localseditorview' and I defined MobileUnion.view.LocalsEditor to include an alias of widget.localseditorview. I feel like I should get the view when I do this.
By the way, I did define the view in the views attribute of my app.js, so that's not it.
Further information: there's no actual error being returned in my webkit console. Just the call to console.log() noted above in my controller returns undefined, rather than the view object.
Question: What do I have to do to make this function return the view, and not undefined? Any help would be appreciated. I've looked to make sure it's not just a typo; it does not seem to be.
The "refs" is to create references to existing components. So far all you've done is declare a class, from what you've posted you've never instanced it anywhere.
You might want to read the docs about autoCreate here:
http://docs.sencha.com/touch/2-1/#!/api/Ext.app.Controller-cfg-refs

Events not caught by Controller

I am trying to respond to a view-fired event inside a controller. The event does fire, but the controller action is never called.
View:
Ext.define("MyApp.view.Dashboard", {
extend: 'Ext.Container',
xtype: 'my_dashboard',
config: {
items: [
{
xtype: 'dataview',
listeners: {
itemtap: function(sender, index, elem, record) {
// fires with param, e.g. 'inbox'
this.fireEvent(record.get('name'));
}
}
}
...
Controller:
Ext.define('MyApp.controller.Dashboard', {
extend: 'Ext.app.Controller',
config: {
control: {
'my_dashboard': {
'inbox': 'showInbox',
...
}
}
},
showInbox: function () {
/* never gets called */
},
...
What am I doing wrong?
UPDATE:
I found a solution, but it feels very hacky. I added a bubbleEvents config to the dataview and the my_dashboard view, and the events started making their way up to the controller.
Since the dashboard can have a variable number of items, I don't know which events I need to bubble up. Of course, I could bubble up all possible dashboard events, but that just seems like a massive kludge.
Should the view fire an application event instead, e.g. MyApp.app.fireEvent()?
I would put an itemId on the dataview.
itemId: 'my_dashboard_dataview'
Then in your controller...
control: {
'#my_dashboard_dataview': {
'itemtap': 'showInbox',
...
}
}
UPDATE
Here is some code that should get you started:
Controller:
Ext.define('MyApp.controller.Dashboard', {
extend: 'Ext.app.Controller',
config: {
control: {
'my_dashboard': {
painted: 'onDashboardPainted',
inbox: 'showInbox'
}
}
},
onDashboardPainted: function(dashboard, eOpts) {
dashboard.down('dataview').on('itemtap', function(sender, index, elem, record){
dashboard.fireEvent(record.get('name'));
//check the console to make sure you the value is: inbox
console.log(record.get('name'));
});
},
showInbox: function () {
console.log('showInbox init');
},
This is definately a scope issue... in your controller add a painted function for my_dashboard... the first function variable will be the my_dashboard component itself:
painted: function(dashboard,...
Now in the painted function add the listener dynamically:
dashboard.down('dataview').on( ... rest of listener code ...
Now inside of the listener do dashboard.fireEvent(....);
Sorry for the formatting im on my mobile, if u cant get it to work i will post code tomorrow

Extending controller in ExtJS 4 MVC application

I building my ExtJS 4 application following the MVC structure. I want to make an extendable grid MyGrid with some functionality that I can reuse several times. Therefore, I guess, it should have its own controller which is also extended, so that the functionality is inherited. How is this properly done?
In the code below I illustrate how I extend the controller MyGrid with MyExtendedGrid. I realize that I'm overriding the init function in the MyGrid controller, so that it is never called. Is the problem simply solved by calling the "super" init in MyGrid from MyExtendedGrid init, or merge the control objects? Is that the proper way to do this in the MVC spirit? If so, how?
controller/MyGrid.js :
Ext.define('App.controller.MyGrid', {
extend: 'Ext.app.Controller',
refs: [
{
ref: 'myGridView',
selector: 'mygrid'
}
],
init: function() {
var me=this;
me.control({
'mygrid textfield[name=searchField]': {
change: function() {
var view = me.getMyGridView();
// Do something with view
}
}
});
}
});
controller/MyExtendedGrid.js :
Ext.define('App.controller.MyExtendedGrid', {
extend: 'App.controller.MyGrid',
views: [
'grids.MyExtendedGrid'],
refs: [
{
ref: 'myExtendedGridView',
selector: 'myextendedgrid'
}
],
init: function() {
var me=this;
me.control({
'myextendedgrid': {
// Some control code
// Using getMyExtendedGridView()
}
});
}
});
view/grids/MyGrid.js :
Ext.define('App.view.grids.MyGrid', {
extend: 'Ext.grid.Panel',
alias : 'widget.mygrid',
requires: [
],
store: '', // Not defined here
columns: [ ], // Not defined here
initComponent: function() {
var me = this;
me.tbar = [
'Search',
{
xtype: 'textfield',
name: 'searchField',
hideLabel: true,
width: 150
}
];
me.callParent(arguments);
}
});
view/grids/MyExtendedGrid.js :
Ext.define('App.view.grids.MyExtendedGrid', {
extend: 'App.view.grids.MyGrid',
alias : 'widget.myextendedgrid',
store: 'MyStore',
columns: [
// ...
],
initComponent: function() {
var me = this;
me.bbar = [
//...
];
me.callParent(arguments);
}
});
It's actually a bit trickier...
Here is what we did in our application (we have exact same situation - some kind of base controller, that is reused in many different places)
Keep init function in base controller.
Define common base method in this base controller (like gridRendered - where you need to do something for all controllers all the time).
Subscribe to the events in all child controllers but subscribe events using methods of base controller. It won't work otherwise - base controller doesn't have proper refs to properly subscribed to events.
I can post couple source snippets, but I think it's pretty straightforward.
Ok, after some thinking I decided on the following solution, which has the advantage that mygrid does not need to know about myextendedgrid.
I extend my gridview as in the question.
I gave the base grid its own controller for doing common functionality, for instance deleteButton.setDisable(false) when something is selected in the grid.
Next, I remind myself that using refs:[ (for instance with selector: 'mygrid') would ambiguously point to both instances of the base class any extended instances. When using me.control({ I instead get the relevant grid by traversing from the activated element using up:
me.control({
'mygrid textfield[name=searchField]': {
change: function(searchfield) {
var grid=searchfield.up('mygrid'); // (mygrid or myextendedgrid!)
// Do something with view
}
}
...
The extended grid I give its own controller and here I could use refs. I don't extend the controller from the MyGrid class (but rather from 'Ext.app.Controller'), unless I would like to use functions or variables from the MyGrid controller. All the controllers are started from app.js using:
Ext.application({
controllers: [
'MyGrid'
'MyExtendedGrid',
],
...
In order to get the grid when rows are selected in the grid, I stored the grid in the selection model as below:
In controller/MyGrid.js :
me.control({
'mygrid': {
afterrender: function(grid) {
var selModel=grid.getSelectionModel();
selModel.myGrid=grid;
},
selectionchange: function(selModel, selected, eOpts) {
var grid=selModel.theLookupGrid;
// Do something with view
}
...

How do I get a Sencha controller to respond to a swipe event in a view?

I have a dataview that I would like to detect a swipe on. It'd be great if I could listen for that in the controller, but as far as I understand I can't do that. My testing bears this out. So instead I need to listen in the view for the event. Currently I'm doing that in the initialize method of my data view like so:
initialize: function() {
var el = Ext.get("list");
el.on('swipe', function(event) {
alert(event.direction);
});
}
So a couple of things:
Is my understanding correct, that I have to listen for DOM events like this in the view?
Is this the best way to set the swipe listener on the dataview? I couldn't seem to make it work through the config object.
How do I then let my controller know about the swipe? It will need to manipulate the view when the swipe happens (like change the view size). What are the best practices in this area?
Thanks in advance.
It is always better to put the events for a component inside the controller. So, first create a ref for that dataview in your controller.
refs : {
listView : 'list' //Or a selector to get the reference
},
control : {
listView : {
// Dataview has an "itemswipe" event - not "swipe" event
itemswipe : function(dataview, index, target, record){
//Do here what you want
}
}
}
This should work (not tested).
I think this is what you are after, its the same idea just changing the scope to the controller:
Ext.define('app.controller.myListControler', {
extend: 'Ext.app.Controller',
config: {
refs: {
list: { selector: 'myList', autoCreate: true, xtype: 'myList' }
}
},
init: function () {
},
launch: function () {
this.getList().on('swipe', this.onSwipe);
},
onSwipe: function (event) {
console.log(event.direction);
}
}

How to push Ext.Panel when row selected on Ext.List in Sencha Touch 2.0?

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.