I am working on Sencha Touch 2 application where some buttons are dynamically created depending upon the number of videos returned from JSON.
I have created the buttons but how to set action on those buttons. I mean how to identify, which button was pressed.
Normally in config we have:
config:
{
layout: 'vbox',
fullscreen: true,
listeners:
[
{
delegate: '#button1',
event: 'tap',
fn: 'itemClicked'
},
],
This action will be set for 'button1' only. So how do I set action of 10 buttons for example. and in my action how can I identify which button was pressed.
Thanks,
Thanks guys,
I am adding these buttons to a panel. I solved it using this code:
var b_Panel = Ext.getCmp('bottompanel');
for(var i=0; i<20; i++)
{
var aButton = Ext.create('Ext.Button',
{
text:'button'+i,
margin:8,
id:'button'+i,
itemId:i,
listeners:
{
tap: function()
{
console.log("Item ID is: "+this.getItemId());
}
}
});
b_Panel.add(aButton);
}
Thanks,
Related
I am new to Sencha Touch2 and facing problem while passing data from my Controller to Floating panel on listitem tap. Here is my controller implementation code:
Ext.define('CustomList.controller.Main', {
extend: 'Ext.app.Controller',
requires:['CustomList.view.DatePanel'],
config: {
refs: {
listView: 'listitems'
},
control: {
'main test2 list': {
activate: 'onActivate',
itemtap: 'onItemTap'
}
}
},
onActivate: function() {
console.log('Main container is active');
},
onItemTap: function(view, index, target, record, event) {
console.log('Item was tapped on the Data View');
Ext.Viewport.add({
xtype: 'DatePanel'
});
}
});
Am able to get data in the controller and DatePanel.js is my floating Panel.
DatePanel.js:
Ext.define('CustomList.view.DatePanel', {
extend: 'Ext.Panel',
alias: 'widget.DatePanel',
xtype:'datepanel',
config: {
itemid:'DatePanel',
modal:true,
centered: true,
hideOnMaskTap:true,
width:'500px',
height:'650px',
items:[
{
styleHtmlCls:'homepage',
tpl:'<h4>{name3}</h4>'
},
{
xtype:'toolbar',
docked:'bottom',
items:[{
text:'OK',
ui:'confirm',
action:'ShowTurnOverReport',
listeners : {
tap : function() {
console.log('Ok');
}
}
},
{
text:'Cancel',
ui:'confirm',
action:'Cancel',
listeners : {
tap : function() {
console.log('Cancel');
var panelToDestroy = Ext.getCmp('datepanel');
panelToDestroy.destroy();
Ext.Viewport.add(Ext.create('CustomList.view.Test2'));//Test.js is my list Panel
}
}
}]
}
]
}
});
Help me out in destroying the panel on 'Cancel' Button.
Can anyone please help me. Thanks.
Create instance of panel you want to add first.
var floatingDatePanel = Ext.create('Yourapp.view.YourDatePanel');
Next get data of selected list item on itemTap
var data = record.getData();
Assign this data to floatingDatePanel with setData() method
UPDATE,
after looking at your panel code, I guess you want to set data to first item in panel ie
{
styleHtmlCls:'homepage',
tpl:'<h4>{name3}</h4>'
}
Right ? If so then you need to change following code
floatingDatePanel.setData(data);
to
floatingDatePanel.getAt(0).setData(data);
Because, it is first item inside panel that is having a template assigned and hopefully the same where you want to set data.
then finally, you can add this panel into viewport with
Ext.Viewport.add(floatingDatePanel);
Am having a delete button in my EXTJS Application. On clicking the button, am opening a confirmation form, asking the user are they sure to delete the item. The delete button is a part of many forms in my Application. And irrespective of the form being used, am opening the confirmation window.
And on clicking the yes button in the confirmation window, i want to do some action. But these actions have to be specific to the form that was opened first.So, am confused about how to use the same view, the same button, but different actions depending upon the first form that was opened.
View: This is the window that opens on clicking the delete button in any of the forms
Ext.define('app.view.GenMessageWin', {
extend : 'Ext.panel.Panel',
alias : 'widget.genmessagewin',
var fp = {
xtype : 'panel',
itemId : 'MSGPANEL',
width : Width,
height : 150,
cls : 'msg effect1',
layout : 'form',
border : false,
items : [{
xtype : 'panel',
//cls : 'winTitle',
html : msgTxt,
border : 0
}, {
xtype : 'form',
itemId : 'MSGFORM',
border : false,
title : '',
buttonAlign : 'center',
fieldDefaults : {
msgTarget : 'side',
labelWidth : 110,
size : 30
},
buttons : [{
text : LANG.BTYES,
iconCls : 'icon-tick-tb',
iconAlign : 'right',
cls : 'tip-btn',
action : 'delete',
id : 'BTYES'
}, {
text : LANG.BTNO,
iconCls : 'icon-cross-tb',
iconAlign : 'right',
cls : 'tip-btn',
action : 'notDelete',
id : 'BTNO'
} ]
Controller
init : function() {
this.control({
'button[action = delete]' : {
click : this.delete
},
'button[action = notDelete]' : {
click : this.notDelete
},
So, in the delete action, we have to determine which form has been opened in the first place, and then delete the data accordingly.
You have 3 options:
1) Make the selector more specific:
'form1 button[action=delete]': {
click: this.form1Delete
},
form1Delete: function(){
this.showMsg(function() {
// form 1 delete
});
}
2) Traverse back up the component hierarchy and find the open form
onDelete: function(btn) {
var form = btn.up('form'); // find an xtype form or subclass
if (form.someCondition) {
//foo
} else {
//bar
}
}
3) As suggested by Dmitry. You'll need to convert it over to 'MVC style'.
Ext.define('ConfirmButton', {
extend: 'Ext.button.Button',
title: '',
msg: '',
requires: ['Ext.window.MessageBox'],
initComponent: function(){
this.callParent();
this.on('click', this.handleClick, this);
},
handleClick: function(){
Ext.MessageBox.confirm(this.title, this.msg, this.checkResponse, this);
},
checkResponse: function(btn){
if (btn == 'yes') {
this.fireEvent('confirm', this);
}
}
});
Ext.onReady(function(){
var btn = new ConfirmButton({
renderTo: document.body,
text: 'Foo',
title: 'Should I',
msg: 'Are you sure'
});
btn.on('confirm', function(){
console.log('Do something');
})
});
I am doing something similar; I simply use the native Ext.Msg class
Controller code
,onDelete: function() {
var me = this;
Ext.Msg.show({
title:'Really shure?',
msg: 'Really wanna do this?',
buttons: Ext.Msg.YESNO,
icon: Ext.Msg.QUESTION,
closable: false,
fn: function(btn) {
if (btn == 'yes') {
me.deleteRecord();
}
},
scope: me
});
}
,deleteRecord: function() {
var me = this,
store = Ext.StoreMgr.lookup('datastore');
store.remove(me.selectedRecord);
store.sync();
}
I would recommend you to keep all logic concerning this within the controller. I your case it'seems that's no problem, cause you just catching the button-events. You problem may be that all controllers catch these, if you are using totally the same window.
You can solve this for example by creating the action property value dynamically when creating the window. Like action='onDeleteCar'
I think you should embed the 'confirmation' functionality inside the button, i.e. create your own ConfirmButton class that would first fire a dialog upon pressing and executing the passed handler only if the dialog exited with "yes".
Here is the example implementation:
Ext.define('My.ConfirmButton', {
extend: 'Ext.button.Button',
alias: 'widget.confirmbutton',
dlgConf: {
title: 'Are you sure?',
msg: 'Are you sure you want to delete this?',
buttons: Ext.Msg.YESNO,
closable: false
},
initComponent: function() {
this.callParent(arguments);
// remember the originally passed handler
this.origHandler = this.handler;
this.origScrope = this.scope;
// override current handler to fire confirmation box first
this.handler = this.confirmHandler;
this.scope = this;
},
confirmHandler: function(me, e) {
// show dialog and call the original handler only on 'yes'
Ext.Msg.show(Ext.applyIf({
fn: function(buttonId) {
if(buttonId == 'yes') {
me.origHandler && me.origHandler.call(me.origScope || me, me, e)
}
},
scope: me
}, this.dlgConf))
},
// Method used to dynamically reassign button handler
setHandler: function(handler, scope) {
// remember the originally passed handler
this.origHandler = this.handler;
this.origScrope = this.scope;
// override current handler to fire confirmation box first
this.handler = this.confirmHandler;
this.scope = this;
return this;
},
});
Here is the sample usage:
Ext.create('My.ConfirmButton', {
text: 'Delete me',
renderTo: Ext.getBody(),
handler: function() {
alert('Aww, you deleted something! :(')
}
});
As you see, the confirmation logic is hidden from the outside world, you use this button exactly like you would use a regular Ext.Button (by passing a handler to it). Also, you can override the configuration of the dialog that the button fires (you may want to adjust it to your needs, e.g. allow passing record name to the dialog for a friendlier UI).
Note that the code isn't thoroughly tested, some cases might be left uncovered.
UPD. You need to add an alias (former xtype) to the component class definition so you can use it in ComponentQuery in your controller code, e.g.
this.control({
'confirmbutton[action = delete]' : {
click : this.delete
},
'confirmbutton[action = notDelete]' : {
click : this.notDelete
}
})
The final solution that i used was to declare variables using the global namespace so that they can be accessed from anywhere. On opening the first form, i get the data from the form using the record variable, and assign them a global name like
App1.Var1 = record.data.id;
And, on opening the delete window, these variables can be accessed by App1.Var1 when the buttons are clicked.
Attached is a my controller file .. i basically want to switch views .. adding and removing a panel in a container with 2 buttons .. in the method for home and popular button i am using Ext.create again and again wouldnt that overload my application becoz iam not destroying my views iam adding and removing them .. My main question is how can i create global var 's for this situation like i create var homepanel = Ext.create just once and then i can reuse that var when i want to remove or add it from my mainContainer.. need serious guidance on this .. searched the whole documention but i dont have any clue about it
Ext.define('app.controller.MainController', {
extend: 'Ext.app.Controller',
config: {
refs: {
homeBtn: '#homeBtn',
popularBtn: '#popularBtn',
homePanel: '#homePanel',
mainContainer: '#mainContainer'
},
control: {
homeBtn:{
tap: 'homeBtnAction'
},
popularBtn:{
tap: 'popularBtnAction'
}
}
},
launch: function(app) {
this.callParent(arguments);
console.log("main launched");
var mainCont = this.getMainContainer();
var homepanel = Ext.create('app.view.Home.HomePanel');
mainCont.add(homepanel);
console.log("homePanelAdded");
},
homeBtnAction: function(){
console.log("home page called");
var mainCont = this.getMainContainer();
var homepanel = Ext.create('app.view.Home.HomePanel');
var popularpanel = Ext.create('app.view.Popular.PopularPanel');
mainCont.remove(popularpanel);
mainCont.add(homepanel);
},
popularBtnAction: function(){
console.log("popular page called");
var mainCont = this.getMainContainer();
var homepanel = Ext.create('app.view.Home.HomePanel');
var popularpanel = Ext.create('app.view.Popular.PopularPanel');
mainCont.remove(homepanel);
mainCont.add(popularpanel);
}
});
NOTE: Iam using Ext.define to create my views and using MVC structure.
Use this,
var homepanel = this.getHomePanel() || Ext.create('app.view.Home.HomePanel');
if this.getHomePanel() does not return anything it'll create the panel for you. After that you'll use the already created panel.
Other note, unless you are manipulating the buttons in some manner there is no need to give them an id or a ref.
Set up your button in your view like so
{
xtype : 'button',
text : 'Home Panel',
action : 'goHome'
}
then in the control section of your controller use this
'button[action=goHome] :
{
tap: 'homeBtnAction'
}
One option is : in "launch", you create both views (with Ext.Create) and use Ext.getCmp in action button callbacks to retrieve the previously created views.
1.) I need to add 2 buttons, one below another. My working so far is demonstrated below; It only shows one button, but how can i add another button with a different button image below this button ?
2.) When the user clicks a button, i need to navigate to another screen. How can i do this ?
I need the equivalent of the following objective-c code ?
View1 *view1 = [[View1 alloc] initWithNibName:#"View1" bundle:nil];
[self.navigationController pushViewController:View1 animated:YES];
3.) How can i add a navigation Bar (equivalent to the navigation bar shown in iPhone)
The code for the 1st question;
{
items:[
{
xtype:'button',
text: 'Submit',
ui:'confirm',
handler: function(){
var values = Ext.getCmp('contactForm').getValues();
Ext.Ajax.request({
url: 'http://loonghd.com/service/',
failure: function (response) {
//do something
}, success: function (response) {
// do something
}
});
}
}
]
}
1) For getting two buttons one below the other, you can add two separate buttons (with different ui property) as childs of a form panel. I think, this is what you need.
Just like this,
....
....
items : [
{
xtype:'button',
text: 'Submit',
ui:'confirm', // makes the button color as green
handler: function(){
var values = Ext.getCmp('contactForm').getValues();
Ext.Ajax.request({
url: 'http://loonghd.com/service/',
failure: function (response) {
//do something
},
success: function (response) {
// do something
}
});
}
},
{
xtype:'button',
text:'Second button',
ui:'decline', // makes the button color as red.
listeners : {
tap : function() {
Ext.Msg.alert('You just clicked Second button');
}
}
}
]
....
....
2) 3) For your 2nd and 3rd question, navigationview is the solution.
Solution posted by M-x is great, but it's very advanced level example & also difficult to understand at first instance.
Here's an easy solution of navigatioview from Sencha Docs.
//create the navigation view and add it into the Ext.Viewport
var view = Ext.Viewport.add({
xtype: 'navigationview',
//we only give it one item by default, which will be the only item in the 'stack' when it loads
items: [
{
//items can have titles
title: 'Navigation View',
padding: 10,
//inside this first item we are going to add a button
items: [
{
xtype: 'button',
text: 'Push another view!',
handler: function() {
//when someone taps this button, it will push another view into stack
view.push({
//this one also has a title
title: 'Second View',
padding: 10,
//once again, this view has one button
items: [
{
xtype: 'button',
text: 'Pop this view!',
handler: function() {
//and when you press this button, it will pop the current view (this) out of the stack
view.pop();
}
}
]
});
}
}
]
}
]
});
Maybe a navigation view will work for you? It's the same idea but it's like starting with a UITableView:
http://docs.sencha.com/touch/2-0/#!/example/navigation-view
In the app/controller/Application.js, when you tap on a contact, the detail view gets pushed. All the source is in the examples directory.
onContactSelect: function(list, index, node, record) {
var editButton = this.getEditButton();
if (!this.showContact) {
this.showContact = Ext.create('AddressBook.view.contact.Show');
}
// Bind the record onto the show contact view
this.showContact.setRecord(record);
// Push the show contact view into the navigation view
this.getMain().push(this.showContact);
},
When an item from a list gets selected i execute the following lines of code.
this.details = Ext.create('EventManager.view.EventInfoView');
this.getNavigationView().push(this.details);
so i create a new view, and push it on a navigationview.
In my controller i listen for a tap on an acceptEventButton which is inside newly created view.
Ext.define('EventManager.controller.eventController', {
extend: 'Ext.app.Controller',
config: {
refs: {
acceptEventButton: '#acceptEventButton'
},
control: {
"acceptEventButton": {
tap: 'onAcceptButtonTap'
}
}
},
...
The first time this view gets placed on the navigationview, the button tap works.
When i hit the back button and push another view the button does nothing.
I'd like to solve this by doing the logic as it is now. I'd rather not add the eventlisteners myself while i'm creating the view and then push it.
Any ideas where this problem resides and how to fix?
A new version of sencha architect was released which allows adding not listed properties.
I solved this by adding an action field on my button, and in my controller reacting to that action.
{
xtype: 'button',
id: 'acceptEventButton',
ui: 'confirm',
text: 'Accept',
action: 'acceptEvent'
}
and in my controller i have the following lines of code
control: {
"button[action=acceptEvent]": {
tap: 'onAcceptButtonTap'
}
}
i faced same problem earlier and it was solved by setting autoDestroy: false,at config of my navigationView
its very well working after applying false to this autoDestroy property.hope it will work for you too.
You should change your query as follows:
control: {
"button[id='acceptEventButton']": {
tap: 'onAcceptButtonTap'
}
}
As an extra information: You can also use xtype in these queries.
For example if you have a navigationview as follows:
Ext.define('app.view.Pages', {
extend: 'Ext.NavigationView',
xtype: 'pages',
...
}
and you push a list to it like this:
Ext.define('app.view.ItemList', {
extend: 'Ext.dataview.List',
xtype: 'itemlist',
...
}
then you can write your query as follows:
control: {
"pages itemlist": {
itemtap: 'onItemTap'
}
}