Sencha Touch 2 button loose listener - extjs

I have a button in a Sencha Touch 2 project.
The button gets destroyed with the view after being pressed and is rebuild after another button gets pressed.
But the button does not get the listener again.
the listener is build in the controller of the view.
Ext.application({
name: 'App',
controllers: ['Main','Home'],
views: ['Main','Home'],
launch: function () {Ext.Viewport.add({xtype:'mainview'});}
});
the controller
Ext.define('App.controller.Home', {extend: 'Ext.app.Controller',
config: {
refs: {homeView: '#homeview',backBtn: '#btn_test1'},
control: {
backBtn: {
tap: function(backBtn){
console.log('[Controller][Home] btn monatsrate - - tap');
Ext.Viewport.add({xtype: 'mainview'});
Ext.Viewport.setActiveItem(1);
}
},
homeView: {
deactivate: function (homeView){
console.log('[Controller][Home] autodestroy homeview');
//homeView.destroy();
Ext.Viewport.remove(homeView);
}
}
}
},
});
And the view
Ext.define("App.view.Main", {
extend:"Ext.Container",
xtype:"mainview",
config:{
id:'mainview',
items:[
{
xtype:'button',
id:'btn_test2',
text: 'test2'
}
]
},
});
Any idea how to allow the button to get the listener back?

This is because the "ref" in your controller is using the id of the button to create the ref. Instead, use a different selector for your button. For example you could give your button a "name" property and give it a value of "testbutton". Then your ref would be like
refs: {homeView: '#homeview',backBtn: 'button[name=testbutton]'},
I struggled with this same problem for buttons and list items that were created/destroyed many times throughout the application's flow. Since then I've read a few times that, in general, the Sencha Touch team recommends not using the id as the selector unless you have a specific reason to. The "name" method above works very well for me. You could use lots of other css-style selectors as well (you'd have to read up on that separately).
As mentioned in a previous comment, I would accept some answers to increase the probability of getting an answer to your questions in the future. I'm just answering this one because I beat my head against the wall on this issue for 4 hours.

Sencha's examples recommend using action config on buttons, like 'cancel', 'goHome', 'createPost', etc.. which kinda makes sense.
All refs are then in the form of: myContainer button[action=myAction]

I believe your issue is exactly the id parameter. If you ever add any id you should make sure it is unique, thus adding an id to a config of your custom view will result in no way to create more then one instance of it! I may not be a 100% right(might be inside a container but i believe it will cause issues anyway) but why would you want an id that much? Besides, you can simply reference your view by xtype:
refs: {homeView: 'homeview',backBtn: 'btn_test1'},
regards,

Related

Add logic to Ext.Component initialize Sencha Touch

I've an application that need to be multilanguage.
The translations comes from the server and are based on the user that is using the application.
My current approach is to create my own field for everything that is used in the app, and during the initialize, I change what it says to the translated text, based on a given code.
For example, in a button, I create my own button like this:
Ext.define('myapp.view.shared.MyButton', {
extend: 'Ext.Button',
xtype: 'myappbutton',
initialize: function () {
this.callParent();
this.setText(myapp.util.Helper.getTranslation(this.textCode, this.defaultText));
}
})
Then I change de default button configuration to something like this, where I just change the xtype, remove text, and add textCode and defaultText.
{
xtype: 'myappbutton',
textCode: 'back',
defaultText: 'Back',
...
}
Then I define the text code and the default text. The getTranslation method, inspects in a local storage to get the translation for the code, and return the finding, or the default text sent.
¡Here is the question!
Since I've 12 different components (so far), and every component extends in some way from Ext.Component, I want to add my code to the initialize of Ext.Component, in order to apply this piece of code, avoiding this crap of creating a custom control for each different control that I need to give translations. Is this possible ?
TIA!
Milton.-
I guess you can always try something along the lines
Ext.define('MyApp.override.Internationalization',{
override:'Ext.Component',
initialize: function () {
me.callOverridden(arguments);
// Your code here.
}
});

Sencha Touch 2 - Text Overlapping Issue

I'm a new developer in Sencha Touch 2 and I'm trying to create my first application using its provided MVC architecture. I find issues with toolbar/titlebar text overlapping when navigating between pages. Take a look at these screenshots:
Example 1
Example 2
I'm not pretty sure what's happening out there. I am using animateActiveItem and routing method to move across my application.
Users.js controller file, login method
// Ajax code here, not included here
// on ajax success:
this.redirectTo("login");
Routes.js controller file
routeLoginPage: function() {
console.log("routeLoginPage");
Ext.Viewport.animateActiveItem({ xtype: "loginpage" }, { type: "slide", direction: "left" });
},
Has anybody really faced a problem like this? I have no idea what to do right now as I was trying to resolve this issue for 2 days+.
EDIT
Basically I need to move across the pages defined as views. I define each view in different file containing properties: extend, requires, alias, config and methods defined by me. Every config property has titlebar attached as its first item.
When I'm trying to change page, I load another view by controller command which changes address hash. Routes controller then fires an animateActiveItem method which loads another View (defined previously as xtype by alias property).
I was using Miami Coder's Tutorial (miamicoder.com/2012/how-to-create-a-sencha-touch-2-app-part-1/) to learn Sencha Touch basics.
I think you mean title bar and not toolbar...
Use navigation view to navigate between views instead of Ext.Viewport.animateActiveItem
It is a better method. For using navigation view use this guide in sencha docs...
Sencha has a steep learning curve so be ready for frustrations like this...
Navigation View Guide
You can add your required views in one panel class and enable the required view using
mainclass.setActiveItem(0)
or else use the navigation view
{
xtype: 'navigationview',
id: 'navView',
navigationBar: {
hidden: true
}
}
The above code will hide the title bar generated by navigation view... Now you need to define your own titlebar like so
{
xtype: 'titlebar',
title: 'title',
items: [
{
xtype: 'button',
text: 'back',
listeners: [
{
fn: function(button){
Ext.getCmp('navView').pop();//this will pop the view and show previous view
},event: 'tap'
}
]
}
]
}
Hope it helps...

Extjs4, How to call controller action method from view?

I want to call method in controller from view when click a cell in grid.
{ header: "<img src='/Content/images/icons/page_white_acrobat.png'/>", width: 30, dataIndex: 'documents', sortable: true, renderer: this.hasDocument,
listeners: {
click: function () {
//how to call method in controller?
}
}
},
Anybody know, please advice me.
Thanks!
You will have a lot of tutorials for extjs 4 on the official forum of the project by Sencha.
When I provide some usefull link to good starting tutorials... with a specific one's about grid management... I think people could look at it really before voting down. Look at it and see yourself some very better ways to do what the question asker wants to do.
Providing direct answers are not always the best way to learn.
Anyway... the following will do the trick:
var controller = this.getController(Ext.String.capitalize(config.controller));
/* where config was an argument of your callback method) */
I suggest you to decouple as much as possible View from Controllers and View from Model. If you look at the projects I have linked, you will find in the Viewport.js a good way to do that. It is calling the controller with .callParent(arguments) method call at the end of these short script.
I am sure the original person have come across the answer or did something to do the trick.
But for the people that may have the same question here is a quick example of what to do:
Don't put a listener in to (MVC)-VIEW of your application. Give the element an ID (in this case the grid)
In the (MVC) - CONTROLLER add this function:
init : function(app) {
this.control({
'myWindow': {
afterrender : this.doAfterRender
/*SAMPLE*/
},
'myWindow #someGrid_ID' : {
select: this.doSelect
/* THIS FUNCTION IS LOCATED in the Controller*/
}
});
},
doSelect : function() {
/*....*/
}
now the controller will listen for the event and react on it.
I hope this helps a few people who might struggle with this.
look at :
http://docs.sencha.com/extjs/4.1.0/#!/guide/application_architecture
http://docs.sencha.com/extjs/4.1.0/#!/api/Ext.dom.Query
Dom Query - Explained:
"myWindow #someGrid_ID" - The dom Query note the # it refers to the ID of the element.
"myWindow" - refers to my window's Alias.
"someGrid_ID" - refers to my grid's ID.
(The grid is a child element of "myWindow")
hope this helps

ExtJS4 - how to get parent grid on selectionchange?

I have little experience with ExtJS3 and now starting with version 4.
In my controller, I have this:
init: function ()
{
this.control({
"userlist":
{
selectionchange: function (view, selected, opts)
{
//get to grid??
}
}
});
}
How can I access the grid that this event happened on, without using id's?
I want to enable/disable buttons on the grid toolbar (tbar) if there are items selected, but I don't want to give anything id's (not the bar, not the individual buttons)
EDIT: the solution was to use the refs property in the controller:
refs:
[
{
ref: "list",
selector: "userlist"
}
],
selectionchange: this.activateTbButtons
activateTbButtons: function (selected, opts)
{
if (selected.selected.length == 1)
{
var tb = this.getList().query("toolbar");
}
}
Just found out that you can use the attribute view, and views under Ext.selection.Model.
This can be useful in cases when you let's say open multiple instances of your objects.
So, to access the grid in your example:
selectionchange: function (view, selected, opts) {
//get to grid??
var grid = view.view.ownerCt;
}
Having the same problem and found the previous answers missing some points. In short, I recommend:
selectionchange: function (selModel, selected, eOpts) {
var grid = selModel.view.ownerCt;
}
This was already proposed by Adezj although it referred to the selectionchange event that has the view as the first argument, and is not applicable to ExtJS 4.0.7+. (Don't think that selectionchange ever had the view as an argument?)
Note that this might not be officially supported by ExtJS since the view property of the selection model is not mentioned in the API docs at all.
Another approach is to use Ext.ComponentQuery.query(...) or defining refs in the controller, as proposed by Arun V, which is basically just a handy wrapper for Ext.ComponentQuery.query(). This works fine if you only have individual instances of the grid class but you need to take care in case you have multiple instances of the same grid class. Simply doing Ext.ComponentQuery.query('xtype-of-your-grid') will return all instances of your grid and you will have lots of fun finding out in which one the user has selected something.
So, in general, I would highly recommend to always work your way up from the component or object that fired the event to be sure you are in the right branch of the component hierarchy unless you are sure you will never have more than one instance of that class you write a controller for.
EDIT
I took a look at the docs for the selectionChange event:
selectionchange( Ext.selection.Model this, Ext.data.Model[] selected, Object eOpts )
The view is not being passed in to the selectionchange handler. An easy way to handle this is to either use Ext.getCmp() or use refs as seen in the docs for Ext.app.Controller:
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.app.Controller
//get grid
var grid = selectionModel.view.ownerCt.ownerCt;

The role of controllers in Backbone.js

If I created a standard webapp with 3 different "states": index, view, edit, would I create a single controller that had 3 different routes?
Assume the index has 4 Backbone.Views associated with it and edit has 3. If one navigates from index to edit: is it standard to change the appearance of the page by simply removing all the index Backbone.Views and rendering the edit ones? That seems like a lot of work - would it be wise to just toggle "display:none" when moving between modes? If so would that functionality be within the Controller's functions?
For instance would the following be a valid way of doing it?
window.MyController = Backbone.Controller.extend({
routes: {
'#index':index,
'#view/:id':view,
'#edit/:id':edit
},
switchState: function(state){
hideStates();
showState(state);
},
index: function(){
switchState(index)
},
view: function(id){
switchState('view')
},
edit: function(id){
switchState('edit')
}
})
That's exactly what you should do. Re-rendering on is a bad idea, because you would have to remember states (ie. user typed something into a field in edit tab, then switched to index - when he's back to edit, the field would be empty). It's also faster to base navigation on simply hiding&showing appropriate layers.

Resources