I've just started working with Sencha Touch over the past couple days and I've run into a few questions. The main one is, when working with anything that doesn't regularly have user click interaction (titlebar, html text, etc for some random examples), is it possible to click on things like this and get a panel to appear.
I know that with buttons and other things, you have a tap, itemtap, etc, but I'm not sure about instances like this. Any help would be appreciated with examples.
Yes you can. Check out my blog post here: http://www.senchahackers.com/touch/multiple-tap-listeners-one-xtemplate/ that explains exactly how to do that.
Basically you can listen for a tap event on any element, as long as you add it to the list of 'delegates'
In your view:
listeners: {
tap: {
element: 'element',
delegate: '.app-box, .doc-box, .bubble-holder',
fn: function(e){
var url = e.target.name,
divClassName = e.delegatedTarget.className,
appbox = "app-box",
docbox = "doc-box",
bubble = "bubble-holder";
console.log(divClassName);
switch(divClassName){
case docbox :
//lets say you have an element '.doc-box' that you want to click and show the panel
// show the panel, which is a separate file, shown below
var profileController = YourApp.getController('YourController');
//call the showProfilePanelPopup() method in your controller, passing in this as the element that shows it
profileController.showProfilePanelPopup(this);
break;
case appbox :
alert(appbox);
break;
case bubble :
alert(bubble);
break;
}
}
}
}
Then in your controller:
extend: 'Ext.app.Controller',
config: {
refs: {
profilePanelPopup: {
autoCreate: true,
selector: '#profilePanelPopup',
xtype: 'profilePanelPopup'
}
}
},
showProfilePanelPopup: function(btn, action, values) {
var me = this;
var popup = me.getProfilePanelPopup();
popup.showBy(btn);
popup.on('hide', function () {
popup.destroy();
}, this);
}
Assuming you some Panel in your views directory like this:
Ext.define('App.view.ProfileNowPop', {
extend : 'Ext.Panel',
alias: 'widget.profileNowPop',
xtype: 'profilePanelPopup',
config: {
height: (Ext.os.deviceType != "Desktop") ? "35%" : 253,
cls:'profilePop',
left: '1%',
padding: 0,
top: '1%',
width: (Ext.os.deviceType != "Desktop") ? '40%' : '36%',
hideOnMaskTap: true,
modal: {
cls:'opaquemask'
},
scrollable: false,
store: 'ProfilePopStore',
model: 'App.model.ProfilePopModel',
items:[
{
xtype: 'fieldset',
items: [
{
xtype: 'textfield',
id: 'gradePopField0',
cls: 'gradePopField',
style: 'background: #f7f7f5',
listeners: {
initialize: function(ele, eOpts) {
this.setReadOnly(true);
}
}
}
]
}
]
},
initialize: function() {
this.callParent(arguments);
}
});
Related
Im really new to this java script and Sencha touch so sorry if this question is simple but I didn't find a way to do this.
I have a function that returns a value .
now I want to display the value from the function inside an html line.
how im calling this function from html element? how I show the value?
config: {
title: 'Me',
iconCls: 'user',
//layout: 'fit',
/* create a title bar for the tab panel */
items: [
{
docked: 'top',
xtype: 'titlebar',
title: 'Singers'
},
{
html: [
'<h1>Hi!! ' + this.setName +'</h1>'
].join("")
}
],
},
setName: function (val) {
var store =Ext.getStore('user');
var last = st.last('user');
return val=(last.get('user'));
}
});
You could use the itemId property to reference the component and then update its html property via the initialise listener.
For example:
config: {
title: 'Me',
iconCls: 'user',
//layout: 'fit',
/* create a title bar for the tab panel */
items: [
{
docked: 'top',
xtype: 'titlebar',
title: 'Singers'
},
{
itemId:'htmlContainer', //use itemIds like div ids
xtype:'container',
html: ''
}
],
/**
* #cfg listeners
* Parent Component listeners go here.
* Check sencha touch doc for more information and other available events.
*/
listeners:{
initialize: 'onInitialise'
}
},
onInitialise: function()
{
//set the html config item here
var c = this.down('#htmlContainer');
c.setHtml(this.setName());
},
setName: function (val) {
....
}
I was wondering if it's possible to not to allow the user to close the item again when it's open, meaning to let it close only when i click on another item in the accordion.
hope it's clear enough.
I'm adding the code:
Ext.define('application.view.SystemHealth', {
extend: 'Ext.Container',
alias: 'widget.globalSynchronization',
requires: ['infra.view.views.BoxHeader',
'application.view.SystemStatusHeader',
'application.model.SystemHealth',
'application.store.SystemHealth',
'infra.utils.pvs.SyncJobRunningStep',
'application.view.CostCalculation',
'application.view.SystemStatusHeader',
'application.view.DataCollector',
'application.view.PublicCloudConnection',
'Ext.layout.container.Accordion'
],
layout:{
type:'vbox',
align:'stretch'
},
header: false,
cls: ['global-synchronization'],
syncJobStatus: null,
initComponent: function() {
var me = this;
me.store = Ext.create('itfm.application.store.SystemHealth');
me.store.load({scope: me, callback: me.onLoadDone});
Ext.apply(me, {
items: [
{
xtype: 'boxHeader',
width: '100%',
title: itfm.application.T.GlobalSynchronizationTitle
},
{
xtype: 'label',
width: '90%',
html: itfm.application.T.GlobalSynchronizationDescription,
margin: "0 0 30 10"
}
]
});
me.callParent(arguments);
},
onLoadDone: function(records, operation, success){
var me =this;
var accordionItemsMargin = '0 0 30 0';
me.accordion = Ext.create('Ext.panel.Panel', {
margin: "0 0 30 10",
defaults:[{
layout:'fit',
height:'100%',
width:'100%'
}] ,
layout: {
type: 'accordion',
titleCollapse: false,
animate: true,
activeOnTop: true,
fill : true,
collapseFirst :true
},
items: [
{
height: 180,
xtype: 'dataCollector',
autoScroll:true,
margins: accordionItemsMargin,
store: records[0].dcModule()
}
,
{
xtype: 'costCalculation',
margins: accordionItemsMargin,
store: records[0].ccModule()
},
{
xtype: 'publicCloudConnection',
margins: accordionItemsMargin,
store: records[0].pcModule()
}
]
});
me.add( me.accordion);
}
});
thanks for the help
What you want is that nothing happens when the user click on the currently expanded panel, instead of collapsing and expanding the next one, is that right?
Unfortunately, there's no built-in option for that... If you really want it, you'll have to override Ext.layout.container.Accordion and implement it yourself.
Edit
In fact most of the collapsing/expanding code lies in the Ext.panel.Panel class.
This simple override seems to be enough to do what you want. Apparently this method is used only for collapse listeners, so it shouldn't have any adverse effect (unless the method is also used somewhere in your code...).
Ext.define('Ext.ux.Panel.JQueryStyleAccordion', {
override: 'Ext.panel.Panel'
,toggleCollapse: function() {
if (this.collapsed || this.floatedFromCollapse) {
this.callParent();
}
}
});
See this fiddle.
I was able to override the accordion with the following
Ext.define('itfm.application.view.SystemHealthAccordion', {
extend: 'Ext.layout.container.Accordion',
alias: ['layout.systemHealthAccordion'] ,
constructor: function() {
var me = this;
me.callParent(arguments);
},
onComponentExpand: function(comp) {
var me = this;
me.callParent(arguments);
var button = comp.down('tool');
button.setDisabled(true);
},
onComponentCollapse: function(comp) {
var me = this;
me.callParent(arguments);
var button = comp.down('tool');
button.setDisabled(false);
}
});
inside the class of the first item of the accordion, there is a need to do the following:
me.on('boxready', me.disableTools);
},
// disable the click on the item in case it's open
disableTools: function(){
var me = this;
var button = me.getHeader().down('tool');
button.setDisabled(true);
}
so when the first item is open it will have the same behaviour
I have following problem. I have grid with tbar. Inside tbar I have number of Ext.form.field.Trigger.
When the user click on trigger button I want to filter the store using function that is provided with grid. I want to define functionality of triggerclick inside defined class, so I can reuse this component with different grid.
So, in short I want to find the panel where clicked component is placed and call panel function, or pass reference of panel to triggerclick, or fire an event with some parameter that will calculated based on where the button was clicked, or maybe there is a better method to accomplish this.
The code (FilterField -> extension of trigger):
Ext.define('GSIP.core.components.FilterField', {
extend: 'Ext.form.field.Trigger',
alias: 'widget.filterfield',
initComponent: function() {
this.addEvents('filterclick');
this.callParent(arguments);
},
onTriggerClick: function(e, t) {
//Ext.getCmp('gsip_plan_list').filterList(); - working but dont want this
//this.fireEvent('filterclick'); - controller cant see it,
//this.filterList; - is it possible to pass scope to panel or reference to panel
//e.getSomething() - is it possible to get panel via EventObject? smth like e.getEl().up(panel)
}
});
code of panel:
Ext.define('GSIP.view.plans.PlanReqList', {
extend: 'Ext.grid.Panel',
alias: 'widget.gsip_devplan_list',
id: 'gsip_plan_list',
title: i18n.getMsg('gsip.view.PlanReqList.title'),
layout: 'fit',
initComponent: function() {
this.store = 'DevPlan';
this.tbar = [{
xtype: 'filterfield',
id: 'filter_login',
triggerCls: 'icon-user',
//scope:this - how to pass scope to panel without defining onTriggerClick here
// onTriggerClick: function() {
// this.fireEvent('filterclick'); //working event is fired but controller cant see it
// this.filterList; //this is working but i dont want to put this code in every filterfield
// },
// listeners : {
// filterclick: function(btn, e, eOpts) { //this is working
// }
// },
}];
this.columns = [{
id: 'id',
header: "Id",
dataIndex: "id",
width: 50,
sortable: true,
filterable: true
}, {
header: "Name",
dataIndex: "name",
width: 150,
sortable: true,
filterable: true
}, {
header: "Author",
dataIndex: "author",
sortable: true,
renderer: this.renderLogin,
filterable: true
}];
this.callParent(arguments);
},
filterList: function() {
this.store.clearFilter();
this.store.filter({
property: 'id',
value: this.down("#filter_id").getValue()
}, {
property: 'name',
value: this.down("#filter_name").getValue()
});
},
renderLogin: function(value, metadata, record) {
return value.login;
}
});
part of code of Controller:
init: function() {
this.control({
'attachments': {
filesaved: this.scanSaved,
}
}, {
'scan': {
filesaved: this.attachmentSaved
}
}, {
'#filter_login': {
filterclick: this.filterStore //this is not listened
}
});
},
filterStore: function() {
console.log('filtering store');
this.getPlanListInstance().filter();
},
Controller can listen to anything. Just need to specify exactly what to. But I would fire events on the panel level - add this into your trigger handler:
this.up('panel').fireEvent('triggerclicked');
I am developing an application in which when submit button is clicked in the form, it should go to a different screen. However it is just printing the results outside of the window and not really going to a new screen. I have hardcoded the store to make sure there is data when I start the application and it still prints it outside of the viewable area.
Here is my Ext.data.Store:
var store = new Ext.data.Store({
model: 'jobSummary',
storeId: 'jobStore',
data : [{title: 'This is test'},
{title: 'This is test2'},
{title: 'This is test3'}]
});
Here is the list that I am using it in:
SearchJobsForm.jobsList = Ext.extend(Ext.Panel, {
dockedItems : [ {
xtype : 'toolbar',
title : 'WTJ',
dock : 'top',
items : [ {
xtype : 'button',
text : 'Back',
ui : 'back',
handler : function() {
//back button controller
},
scope : this
} ]
} ],
items : [ {
xtype : 'list',
emptyText : 'No data available.',
store : 'jobStore',
itemTpl : '<div class="list-item-title">{title}</div>'
+
'<div class="list-item-narrative">{narrative}</div>',
onItemDisclosure : function(record) {
},
grouped : false,
scroll : 'vertical',
fullscreen : true
} ],
initComponent : function() {
SearchJobsForm.jobsList.superclass.initComponent.apply(this, arguments);
}
});
And i am calling this list panel from my submit button handler which is:
var jobsList = new SearchJobsForm.jobsList();
The full code I have pasted on this link for better visibility:
http://pastebin.com/a05AcVWZ
Ok,
SearchJobsForm.form is your main panel, it will contains two components a searchForm (with text/select input) and a panel/list of results.
In the callback, we will hide() the form and show() the results list. This is not a clean code, but the simpliest and kissest one I can get from yours.
First let's instantiate the jobsList
// It has the id ( id: 'jobsListId')
var jobsList = new SearchJobsForm.jobsList();
then you should put all your inputs into a form (xtype : formpanel,
id: 'searchFormId')
And add the resultPanel just after the form
Here is the code
SearchJobsForm.form = Ext.extend(Ext.Panel,{
initComponent: function(){
Ext.apply(this, {
id: 'searchForm',
floating: true,
width: 250,
height: 370,
scroll: 'vertical',
centered: true,
modal: true,
hideOnMaskTap: false,
items: [
{
xtype: 'formpanel', // 1. this is the added formpanel
itemId: 'searchForm',
id: 'searchFormId', // this id is important
items: [
{
xtype: 'textfield',
...
}, {
xtype: 'textfield',
...
},
// all your inputs
]
},
// 2. add here the results panel : jobsList
jobsList
], // the code continues inchanged
dockedItems: [{
...
- Finally we will modify the ajax callback to hide/show the panels. Do not remove one of them, elsewhere you won't be able to reset your form
// here it comes
Ext.util.JSONP.request({
url: "http://"+serverAdd+":"+ port+"/users/searchresults.json",
format: 'json',
callbackKey: 'callback',
params : searchCriteria,
callback: function(data) {
console.log('callback');
// Call your list-filling fonctions here
// jobsList.fill(data);
Ext.getCmp('searchFormId').hide();
Ext.getCmp('jobsListId').show();
},
failure: function ( result) {
console.error('Failed');
}
});
For your next projects, I recommend you to work with classes and namespaces to avoid 1000 lined files ; Ext.ns() is your best friend and will avoid you a lot of headaches.
I am working with the Sencha touch framework and there list item component. I have only been working with this for about 2 weeks now and I can not figure out how to get the "onItemDisclosure" to open up the "detailPanel". I am trying to follow this example: http://vimeo.com/19245335. I have pasted my code below. Any help is very much appreciated.
GoW3Guide.views.detailPanel = Ext.extend(Ext.Panel, {
id: 'detailpanel',
tpl: 'Hello, {firstName}!',
dockedItems: [
{
xtype: 'toolbar',
items: [{
text: 'back',
ui: 'back',
handler: function() {
GoW3Guide.Viewport.setActiveItem('disclosurelist', {type:'slide', direction:'right'});
}
}]
}
]
});
Ext.reg('detailPanel', GoW3Guide.views.detailPanel);
GoW3Guide.views.listPanel = Ext.extend(Ext.List, {
id: 'disclosurelist',
store: GoW3Guide.ListStore,
itemTpl: '<div class="contact">{firstName} {lastName}</div>',
grouped: true,
onItemDisclosure: function(record, btn, index) {
GoW3Guide.views.detailPanel.update(record.data);
GoW3Guide.views.Guidescard.setActiveItem('detailpanel');
}
});
Ext.reg('listPanel', GoW3Guide.views.listPanel);
GoW3Guide.views.Guidescard = Ext.extend(Ext.Panel, {
fullscreen: true,
layout: 'card',
cardSwitchAnimation: 'slide',
initComponent: function() {
Ext.apply(this, {
items: [GoW3Guide.views.listPanel, GoW3Guide.views.detailPanel]
});
GoW3Guide.views.Guidescard.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('guidescard', GoW3Guide.views.Guidescard);
Are you getting any javascript errors?
According to the docs setActiveItem either needs a component instance, a number (card index), or a config object, e.g. {xtype:'detailPanel'}
If you want to make a new detail panel active try
GoW3Guide.views.Guidescard.setActiveItem({xtype:'detailpanel'});
or
GoW3Guide.views.Guidescard.setActiveItem(new GoW3Guide.views.detailPanel());