How do I fire an event when a tab is loaded in Sencha Touch? I want to AJAX in some content that isn't important enough to be loaded immediately, and Sencha Touch seems to miss the autoLoad property of ExtJS.
What can I bind to on a panel to detect that the panel has been activated?
You can listen for the event activate in the panel itself or for the event cardswitch in the TabPanel.
The cardswitch event only fires after the first card has been set, so if you want an action to trigger on initialization, add a listener for the activate event on the TabPanel.
Ext.setup({
icon: 'icon.png',
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
glossOnIcon: false,
onReady: function() {
var tabpanel = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
fullscreen: true,
ui: 'light',
cardSwitchAnimation: {
type: 'slide',
cover: true
},
//
// Listen for cardswitch event in TabPanel
//
listeners: {
cardswitch: function(comp, newCard, oldCard, index, animated) {
console.log(newCard.title, oldCard.title, index, animated);
}
},
defaults: {
scroll: 'vertical'
},
items: [{
title: 'About',
html: '<h1>Bottom Tabs</h1><p>Docking tabs to the bottom will automatically change their style. The tabs below are type="light", though the standard type is dark. Badges (like the 4 & Long title below) can be added by setting <code>badgeText</code> when creating a tab/card or by using <code>setBadge()</code> on the tab later.</p>',
iconCls: 'info',
cls: 'card1',
//
// Listen for activate event in panel
//
listeners: {
activate: function(comp){
console.log(comp.title);
//
// Ajax Request
//
Ext.Ajax.request({
url: 'your_url_here.json',
success: function(response, opts) {
//
// Update panel html with ajax response
//
comp.update(response.responseText);
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
}
}
}, {
title: 'Favorites',
html: '<h1>Favorites Card</h1>',
iconCls: 'favorites',
cls: 'card2',
badgeText: '4'
}, {
title: 'Downloads',
id: 'tab3',
html: '<h1>Downloads Card</h1>',
badgeText: 'Text can go here too, but it will be cut off if it is too long.',
cls: 'card3',
iconCls: 'download'
}, {
title: 'Settings',
html: '<h1>Settings Card</h1>',
cls: 'card4',
iconCls: 'settings'
}, {
title: 'User',
html: '<h1>User Card</h1>',
cls: 'card5',
iconCls: 'user'
}]
});
}
});
More info on the Sencha Touch Docs:
http://dev.sencha.com/deploy/touch/docs/?class=Ext.TabPanel
http://dev.sencha.com/deploy/touch/docs/?class=Ext.Panel
Related
I want to present the source code, which is taken from inside a div with jQuery, inside an Ext.Window. I have managed to do that, but my problem is that sometimes the source code is huge, since it contains encoded images and the Ext.Window takes some time to appear in the screen after it is triggered via click event. I would like to present the Ext.Window but with a loading icon until the data is ready.
win = new Ext.Window ({
title:'Source Code',
width:800,
height:300,
items: [{
xtype : 'textarea',
readOnly: true,
value: sourceCode
}]
});
win.show();
Try with a undefined function and a setTimeout function. Do not forget the config layout: 'fit'.
Ext.application({
name : 'Fiddle',
launch : function() {
var win = Ext.create('Ext.window.Window', {
title:'Source Code',
width:800,
height:300,
layout: 'fit',
items: [{
xtype : 'textarea',
readOnly: true,
value: 'test'
}]
});
win.show(undefined, function(){
win.getEl().mask('Loading...');
setTimeout(function() {
win.getEl().unmask();
}, 3000);
});
}
});
Or
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.create('Ext.window.Window', {
title:'Source Code',
width:800,
height:300,
layout: 'fit',
items: [{
xtype : 'textarea',
readOnly: true,
value: 'test'
}]
}).show(undefined, function(){
win.getEl().mask('Loading...');
setTimeout(function() {
win.getEl().unmask();
}, 3000);
});
}
});
TRY
win.show(undefined, function(){
win.getEl().mask('Loading...');
win.suspendEvents();
win.down('textarea').setValue(sourceCode);
win.down('textarea').focus();
win.resumeEvents();
setTimeout(function() {
win.getEl().unmask();
}, 2000);
});
What you can try is to set the value only after the window is already displayed:
win = new Ext.Window ({
title:'Source Code',
width:800,
height:300,
items: [{
xtype : 'textarea',
readOnly: true
}],
listeners: {
afterrender: function(sourceWindow) {
sourceWindow.down('textarea').setValue(sourceCode)
}
}
});
win.show();
Then you can add josei's mask/unmask approach on top of that, although I would recommend that you search some event that happens after the value has been set to remove the mask (you can try the change event on the textarea), because that way your wait wouldn't be a fixed amount of time, but related to the time it takes to render the textarea value.
I try to get an event click on the node's Icon in a tree panel.
I have a tree with many node and in front of the leaf node, I have an Icon.
For the moment, when I click on a node I display a PDF file.
I want to do a specific action when I click on the Icon of this node.
Someone have an idea for do that?
Thanks a lot for your futur answers!
EDIT:
Thanks for your answer,
#Hown_: Ok, but I must do an specific action which depends to the select node. With a CSS selector, I can't do that. I'm wrong?
#budgw: Yes, it's a good solution, but my icon must be in front of the text node :(
I guess the simplest way would be to add itemclick event to your TreePanel and check in the handler fn if the tree icon was clicked by checking the target of the event. It works as simple as this:
You may have to change the css selector of the getTarget fn for your specific use. ( e.g. only leaf elements or pdf icons or something like that )
Ext.onReady(function() {
var store = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [{
text: "detention",
leaf: true
}, {
text: "homework",
expanded: true,
children: [{
text: "book report",
leaf: true
}, {
text: "alegrbra",
leaf: true
}]
}, {
text: "buy lottery tickets",
leaf: true
}]
}
});
Ext.create('Ext.tree.Panel', {
title: 'Simple Tree',
width: 200,
store: store,
rootVisible: false,
renderTo: Ext.getBody(),
listeners: {
itemclick: function(treeModel, record, item, index, e, eOpts){
var iconElClicked = e.getTarget('.x-tree-icon');
if(iconElClicked){
//tree icon clicked
//do something in here
console.log('tree icon clicked');
}
}
}
});
});
I don't think you can do that with the icon in front of the node (maybe I'm wrong).
But I usually solve this kind of use case by using a treepanel with 2 columns :
a treecolumn
an action column like in this example here.
The trick is to use the config property 'hideHeaders:true' on the tree panel to make it looks like a classic tree.
You can select the dom elements of the icons via css selector and add a click event after the render method.
here is an example:
https://fiddle.sencha.com/#fiddle/8kd
UPDATE:
exmaple:
Ext.onReady(function() {
var store = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [{
text: "detention",
leaf: true
}, {
text: "homework",
expanded: true,
children: [{
text: "book report",
leaf: true
}, {
text: "alegrbra",
leaf: true
}]
}, {
text: "buy lottery tickets",
leaf: true
}]
}
});
Ext.define('MyPanel', {
extend: 'Ext.tree.Panel',
title: 'Simple Tree',
width: 200,
onTreeIconClick: function(treeModel, record, item, index, e, eOpts){
// DO SOMETHING IN HERE
console.log('onTreeIconClicked');
},
render: function(){
this.callParent(arguments);
var domEls = this.el.dom.querySelectorAll('#' + this.getId() + ' .x-tree-icon', this.el.dom);
for(var i = 0; i<domEls.length; i++){
Ext.get(domEls[i]).on('click', function(){
//click on tree icon
this.on('itemclick', this.onTreeIconClick, this, { single: true });
}, this);
}
}
});
Ext.create('MyPanel', {
store: store,
rootVisible: false,
renderTo: Ext.getBody()
});
});
I've been learning sencha touch 2.0 over the last 2 weeks and i've stumbled onto two problems. What i would like to do is have a static top bar and bottom bar on my page and let the dynamic content be controlled by buttons placed at the bottom dock. I've spent 4 hours on trying to get this to work the way i want to, i'm almost there but i need a little guidance.
My first problem is that i want to add an image to the static top dock. The code that was suggested in another form does not work.
var topBar = new Ext.BoxComponent(
{
xtype: 'box',
autoEl: {tag: 'img', src:'/resources/icons/icon.png'}
}
)
This code doesnt give any errors but it also doesnt show the required image. The image is 60px by 30px
The second problem i'm having is that i would like to add icons to my bottom dock so that when the user click on them, the page would change to show a new page. I have a form with 3 fields that i would like to link to one of the icons on the bottom dock so when the icon is clicked, the form would show. Here is the full code:
Ext.setup({
phoneStartupScreen : 'resources/images/icon.png',
icon : 'resources/images/Homescreen.png',
glossOnIcon : false,
onReady : function() {
var topBar = new Ext.BoxComponent(
{
xtype: 'box',
autoEl: {tag: 'img', src:'/resources/icons/icon.png'}
}
)
var tapHandler = function (btn, evt) {
alert("Button '" + btn.text + "' tapped.");
}
var form = new Ext.form.FormPanel({
items:
[
{
xtype: "textfield",
name: "name",
label: "Name",
placeHolder: "your name here"
},
{
xtype: "emailfield",
name: "email",
label: "Email",
placeHolder: "you#example.com"
},
{
xtype: "urlfield",
name: "url",
label: "Url",
placeHolder: "http://www.example.com"
}
]
})
var searchPageContent ={
html:'This is a test for search page'
}
var userPageContent ={
html:'This is a test for user page'
}
var dockedItems = [
{
xtype : 'toolbar',
dock : 'top',
items : topBar
},
{
xtype: "toolbar",
dock: "bottom",
items: [
{
xtype: 'spacer'
},
{
iconMask: true,
iconCls: "favorites",
items: form
},
{
xtype: 'spacer'
},
{
iconMask: true,
iconCls: "search",
items: searchPageContent
},
{
xtype: 'spacer'
},
{
iconMask: true,
iconCls: "user",
items: userPageContent
},
{
xtype: 'spacer'
},
]
}
]
new Ext.Panel({
id : 'buttonsPanel',
fullscreen : true,
dockedItems : dockedItems
});
}
});
as mentioned before, i have been able to create the static top and bottom bars but my image does not work in my top bar, which is my first problem, and when i click one of the 3 buttons, nothing happens; i would like my form to be displayed when i click my favorites button but nothing happens. Where have i gone wrong?
Thank you
After a few days of wrestling with sencha, i found an example that almost had what i wanted so modified it and it worked out exactly the way i wanted. I now have a static top bar and a static bottom bar with page icons such that when i click the page icons, the main content scrolls and the new page is displayed.
Ext.setup({
onReady: function() {
var topBar = new Ext.BoxComponent({
layout: 'hbox',
html:
'<img src="resources/icons/icon.png" height="30", width="48"/>',
flex: 1,
style:{
textAlign: 'center'
}
})
var dockedItems = [
{
//this creates the top bar, places it at the top of the page and gives it a background image
xtype : 'toolbar',
dock : 'top',
style: 'background-image:url("resources/images/backgroundSmall.png"); background-repeat: repeat-x;',
items : topBar
}
]
// Sub-page sections
// Main portion of the page, which includes top toolbar and content
var welcome = new Ext.Panel({
items: [{
html: 'this is the welcome screen'
}],
title: "Welcome",
iconCls: "welcome",
});
var search = new Ext.Panel({
items: [{
html: 'this is the search screen'
}],
title: "Search",
iconCls: "search",
});
// This is the outer panel with the bottom toolbar
var wrapper = new Ext.TabPanel({
fullscreen: true,
tabBar: {
dock: 'bottom',
style: 'background:#8a9cB2;',
layout: {
pack: 'center'
}
},
items: [
welcome,
search,
{
iconMask: true,
iconCls: "search"
},
{
iconMask: true,
iconCls: "user"
}
],
dockedItems: dockedItems
});
}
});
I have a gridpanel that allows inline editing of a column. This column uses a combobox as the editor, and neither the "change" event nor the "select" event give me something usable to backtrace the edited value to get the changed row from the gridpanel.
I believe Ext floats the editor's combobox so therefore I can't do something simple like
combo.up()
To return to the grid.
Here is the grid panel from the view:
{
xtype: 'gridpanel',
title: 'Important Projects',
id: 'importantProjectsGrid',
dockedItems: [],
flex: 1,
columns: [
{ header: 'Quote Name', dataIndex: 'QuoteName', flex: 4 },
{ header: 'Quote Status', dataIndex: 'QuoteStatusID', flex: 6, editor: {
xtype: 'combobox',
editable: false,
action: 'QuoteStatus',
selectOnTab: true,
store: 'statuses',
queryMode: 'local',
displayField: 'Description',
valueField: 'Description'
} }
],
store: 'myimpprojects',
selModel: {
selType: 'cellmodel'
},
plugins: [Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})]
}
Here is the controller code pertaining to this:
init: function () {
this.control({
'[action=QuoteStatus]': {
change: function (combo, new_value, old_value, opts) {
// I need to go back up from this combobox
// to get the row that this value was edited in
// to grab an ID value from that row's data
// in order to make an ajax request
}
}
});
},
Thanks for any help!
You can monitor store's update event.
init: function () {
this.getMyimpprojectsStore().on('update', function(store, record) {
// do something with record
});
// ...
},
Try putting the listener on the CellEditing plugin. There are events for beforeedit, edit, and validateedit that receive an object containing references to the grid, the record, field, row and column indexes, and more. You should be able to check for the combobox in the event handler and handle your information from there.
Quick link to the doc page: Ext.grid.plugin.CellEditing
I'm convinced that the update plugin will handle the update automatically, through the api of the underlying store and post the data automatically to the server if the proxy as autoSync to true.
Example of the configured proxy:
Ext.define('MyApp.store.YourStore', {
extend: 'Ext.data.Store',
model: 'MyApp.model.YourGridModel',
autoSync: true, //Commits the changes realtime to the server
proxy: {
type: 'ajax',
batchActions : true, //Commits the changes everytime a value is changed if true o otherwise store the changes and batch update them in 1 single post
api: {
read: 'path/to/select',
create: 'path/to/create',
update: 'path/to/update',
destroy: 'path/to/delete'
},
reader: {
type: 'json',
root: 'results',
successProperty: 'success'
},
writer: {
type: 'json',
writeAllFields: true
},
listeners: {
exception: function(proxy, response, operation){
Ext.MessageBox.show({
title: 'REMOTE EXCEPTION',
msg: operation.getError(),
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
}
},
listeners: {
write: function(proxy, operation){
var response = Ext.JSON.decode(operation.response.responseText);
if(response.success == true)
{
//TODO: Proxy - Messageboxes might be a little anoying we might instead use the status bar in teh grid or something so show status of the operation
Ext.MessageBox.show({
title: this.xFileLibraryTitle,
msg: response.message,
icon: (response.success == true)? Ext.MessageBox.INFO : Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
}
}
});
I would look specially for the two configs: "autoSync" and "batchActions"
Hope this helps you further with your issue!
I'm able to hide items among the dockedItems of a TabPanel, but am wanting to temporarily hide the entire dock, because the toolbar itself still takes up space and the rest of the content does not fill the screen.
So far, I do like so:
myApp.views.productList.dockedItems.items[0].removeAll(true);
myApp.views.productList.doComponentLayout();
Alternatively:
myApp.views.productList.getComponent('search').removeAll(true);
myApp.views.productList.doComponentLayout();
But neither removes the dockedItems toolbar itself.
I've even tried to give the dockedItems individually and collectively an id: to remove the whole component, but without luck. I've also tried moving the toolbar in question out from the docked items and into the items: property of the containing panel, but this breaks other things in my app that I'd rather not change at present.
Any clues on how to do this?
If I understand you correctly you want to temporally remove tabBar from a tabPanel. I was able to accomplish this through giving and id to my tabBar and then using removeDocked and addDocked methods. I'm new to sencha-touch so most likely there is a better way of doing this
The code below removes tabBar from tabPanel and then adds it back again.
Ext.setup({
onReady: function() {
var tabpanel = new Ext.TabPanel({
ui : 'dark',
sortable : true,
tabBar:{
id: 'tabPanelTabBar'
},
items: [
{title: 'Tab 1',html : '1',cls : 'card1'},
{title: 'Tab 2',html : '2',cls : 'card2'},
{title: 'Tab 3',html : '3',cls : 'card3'}
]
});
var paneltest = new Ext.Panel({
fullscreen: true,
dockedItems:[
{
xtype: 'button',
text: 'Disable TabBar',
scope: this,
hasDisabled: false,
handler: function(btn) {
console.log(btn);
if (btn.hasDisabled) {
tabpanel.addDocked(Ext.getCmp('tabPanelTabBar'), 0);
btn.hasDisabled = false;
btn.setText('Disable TabBar');
} else {
tabpanel.removeDocked(Ext.getCmp('tabPanelTabBar'), false)
btn.hasDisabled = true;
btn.setText('Enable TabBar');
}
}}
],
items:[tabpanel]
});
paneltest.show()
}
})
в dockedItems добавить button, которая будет обращаться к элементу panel.dockedItems и изменять/скрывать сам dockedItems
function f_create_accord(P_el_id, P_el_params) {
P_el = Ext.create
(
'Ext.panel.Panel',
{
id: P_el_id
, border: false
, x: P_el_params.left
, y: P_el_params.top
, id_el: P_el_params.id_el
, layout: 'accordion'
, dockedItems: [{
xtype: 'toolbar',
dock: 'bottom',
items: [{
P_el_id: P_el_id,
xtype: 'button',
text: 'добавить',
}, {
id_el: P_el_id,
xtype: 'button',
text: 'скрыть',
vision: true,
listeners: {
click: function (el, v2, v3) {
if (el.vision) {
Ext.getCmp(el.id_el).dockedItems.items[0].setHeight(5);
Ext.getCmp(el.id_el).dockedItems.items[0].items.items[0].hide();
Ext.getCmp(el.id_el).dockedItems.items[0].items.items[1].setWidth(Ext.getCmp(el.id_el).getWidth());
el.vision = false
}
else {
Ext.getCmp(el.id_el).dockedItems.items[0].setHeight('15px');
Ext.getCmp(el.id_el).dockedItems.items[0].items.items[0].show();
Ext.getCmp(el.id_el).dockedItems.items[0].items.items[1].setWidth(60);
el.vision = true
}
// Ext.getCmp(el.id_el).dockedItems.items[i].hide();
}
}
}]
}]
}
);
P_el.setStyle('position', 'absolute');
P_el.setStyle('box-shadow', ' 0px 0px 0px 1px green');
P_el.setStyle('background', 'border-box');
return P_el;
}