First of all to stress it: I'm using sencha modern.
Well consider the following view:
Ext.define('myApplication.view.main.OrderView', {
extend: 'Ext.Container',
xtype: 'ordercontainer',
controller: 'order',
requires: [
'Ext.MessageBox',
'Ext.layout.Fit'
],
viewModel: 'main',
defaults: {
tab: {
iconAlign: 'top'
},
flex: 1
},
layout: 'vbox',
items: [
{
xtype: 'button',
text: 'test, to be updated',
height: 30,
flex: 0,
listeners: {
click: 'onClick'
}
},
]
});
With the corresponding controller:
Ext.define('myApplication.view.main.OrderController', {
extend: 'Ext.app.ViewController',
alias: 'controller.order',
onClick: function () {
debugger;
alert('onClick');
}
});
now I can see the button when the page is loaded. I expect the onClick function to be called (as per guide). However it is not. I don't see any alert, nor will (when development console is open in chrome) the debugger halt on the onClick function.
If I change the button to use a handle and use code-behind it works. Yet the view controller doesn't work. This shouldn't fail right? Or did I once again fall into the trap of using a guide for classic?
It's because in Modern the components doesn't have event click but tap
So change your code like this:
items: [
{
xtype: 'button',
text: 'test, to be updated',
height: 30,
flex: 0,
listeners: {
tap: 'onClick'
}
},
]
Related
I’m new here in at Stackoverflow and to Sencha ExtJS development. I’m a student from Germany and I’m current trying to get my degree in media computer sciences. As a part of my final assignment I’m currently developing the UI of a webapp for a local company.
While I was trying out the capabilities of the Sencha ExtJS framework I came across some problems, which is why I’m now reaching out to the community for help ;)
My first problem I had, was when I was playing around with the syntax for instancing classes using xtypes and the association of Stores inside the ViewModel:
For the purpose of easier to read and less cluttered code I wanted to give my stores their own xtype so I could instead of declaring all the stores and their configs inside the ViewModels’ stores config wanted to have every store inside their own file and then just create an instance of them later inside the ViewModel. The code I wrote for this looks like this:
ViewModel:
Ext.define('Example.viewmodel.MyViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myviewmodel',
requires: [
'Example.store.MyStore',
],
stores: {
StoreA: { xtype: 'store_a' },
StoreB: { xtype: 'store_b' },
StoreC: { xtype: 'store_c' }
},
data: {
/* This object holds the arbitrary data that populates the ViewModel and
is then available for binding. */
}
});
StoreA:
Ext.define('Example.store.StoreA', {
extend: 'Ext.data.Store',
xtype: 'store_a',
requires: [
'Example.model.ModelA'
],
storeId: 'StoreA',
autoLoad: false,
model: 'Example.model.ModelA',
listeners: {
load: 'onLoadofStoreA'
}
});
But apparently this isn’t working… My load listener of the store does not seem to fire at the method inside my controller and does not even seem to know about the view that is associated with the ViewModel. What am I doing wrong or is this just not meant to be done like that?
My Second Problem was when I was playing around with some of the UI components. My scenario was like this:
I wanted to have a menu that would slide in, where u could do some inputs that would then load the content for the view.
I found this example for a sliding menu (https://examples.sencha.com/extjs/6.7.0/examples/kitchensink/?modern#menus) and built this:
Inside my ViewController:
getMenuCfg: function (side) {
var cfg = {
side: side,
controller: example_controller',
id: 'topMenu',
items: [
{
xtype: 'container',
layout: 'hbox',
width: '100%',
items: [
{
xtype: 'fieldset',
reference: 'fldSet',
id: 'fldSet',
layout: 'vbox',
width: '50%',
defaults: {
labelTextAlign: 'left'
},
items: [
{
autoSelect: false,
xtype: 'selectfield',
label: 'Selectfield',
reference: 'sfExample',
id: 'sfExample',
listeners: {
change: 'onSFChange'
}
},
{
xtype: 'container',
layout: {
type: 'hbox',
align: 'end',
pack: 'center'
},
items: [{
xtype: 'textfield',
reference: 'ressource',
id: 'ressource',
flex: 1,
textAlign: 'left',
margin: '0 10 0 0',
label: 'Ressource',
labelAlign: 'top',
labelTextAlign: 'left',
editable: false,
readOnly: true
},
{
xtype: 'button',
shadow: 'true',
ui: 'action round',
height: '50%',
iconCls: 'x-fa fa-arrow-right',
handler: 'openDialog'
}
]
},
{
xtype: 'textfield',
reference: 'tfExample',
id: 'tfExample',
label: 'Textfield',
editable: false,
readOnly: true
}
]
},
}]
}];
The problem I come across now is, that I would no longer be able to easily get the references of components inside the menu (input fields) with this.lookupReference() as if they were just part of the view. In fact to find a workaround I had to trace a way back to the components using a debugger.
For example if another method inside my controller wanted to use a field inside this menu, instead of simply just doing this.lookupReference(‘sfExample’) I now had to do something like this:
var me = this,
vm = me.getViewModel(),
menuItems = me.topMenu.getActiveItem().getItems(),
fieldset = menuItems.getByKey('fldSet'),
selectfieldRessArt = fieldsetLeft.getItems().getByKey('sfExample');
I’m pretty sure that I am missing out on something important here and there has to be a way to do this easier. I’m really looking forward to your answers, thank you in advance ;)
use xtype only for components. if you need to define an type/alias for store, use alias config property instead and especify the alias category "store.".
Defining a store with an alias
Ext.define('Example.store.StoreA', {
extend: 'Ext.data.Store',
//use store. to category as a store
alias: 'store.store_a',
requires: [
'Example.model.ModelA'
],
storeId: 'StoreA',
autoLoad: false,
model: 'Example.model.ModelA',
listeners: {
load: 'onLoadofStoreA'
}
});
Instantianting your store by type
Ext.define('Example.viewmodel.MyViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myviewmodel',
requires: [
'Example.store.MyStore',
],
stores: {
StoreA: { type: 'store_a' },
StoreB: { type: 'store_b' },
StoreC: { type: 'store_c' }
},
data: {
/* This object holds the arbitrary data that populates the ViewModel and
is then available for binding. */
}
});
I Hope it can help you
Why is the first listener not working and the other one working?
How to set the first listener to work?
Maybe the problem is related to scope, this?
How can I set this to see the function available in MainControllers?
It is modern version ExtJS 6.2
Structure folders:
//FeedViewer
//app
//view
//main
/MainController.js
/MainModel.js
/FeedForm.js
/Feeds.js
//classic
//modern
//src
//view
//main
/Main.js
MainController.js:
Ext.define('FeedViewer.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
onNewFeed: function () {
alert('Hello');
}
});
Feeds.js:
Ext.define('FeedViewer.view.main.Feeds', {
extend: 'Ext.grid.Grid',
xtype: 'feedslist',
requires: [
'ContactsApp.view.feeds.MainController',
'ContactsApp.view.feeds.MainModel'
],
viewModel: 'feeds',
controller: 'feeds',
columns: [{
dataIndex: 'feed',
text: 'feed'
}],
items: [{
xtype: 'toolbar',
docked: 'left',
items: [{
xtype: 'button'
text: 'Add New Feed',
iconCls: 'fa fa-plus',
listeners: {
click: 'onNewFeed' * * //It doesn't work**
}
}]
}],
listeners: {
select: 'onNewFeed' * * //It works**
}
});
In modern toolkit Ext.Button click event is called tap. Also you can use handler config. Here's the FIDDLE
While using the sencha extjs 6.5 framework I had a problem with the events.. What I wish to do is create a store that postpones loading until after a tab is activated. (and reload each time a person goes back to that tab).
Now manual loading isn't hard. However I can't seem to find the trigger that occurs when a tab is activate.
The tabs are defined by the main view (which is shown as main in app.js):
Ext.define('MyApp.view.main.Main', {
extend: 'Ext.tab.Panel',
xtype: 'app-main',
requires: [
'Ext.MessageBox',
'Ext.layout.Fit',
],
controller: 'main',
viewModel: 'main',
defaults: {
tab: {
iconAlign: 'top'
}
},
tabBarPosition: 'left',
items: [
{
title: 'Users',
iconCls: 'x-fa fa-user',
layout: 'fit',
items: [{
xtype: 'usercontainer',
}],
},{
title: 'Home',
iconCls: 'x-fa fa-home',
layout: 'fit',
items: [{
xtype: 'ordercontainer'
}]
},
]
});
The second tab is the one I'm interested in, it has the following definition:
Ext.define('BinkPortalFrontend.view.main.OrderContainer', {
//extend: 'BinkPortalFrontend.view.main.BaseContainer',
xtype: 'ordercontainer',
controller: 'order',
extend: 'Ext.Container',
layout: 'vbox',
listeners: {
activate: function(me, oOpts) {
console.log('activating');
},
enable: function(me, oOpts) {
console.log('enabling');
},
focus: function(me, oOpts) {
console.log('focus');
},
focusenter: function(me, oOpts) {
console.log('focus');
},
focusleave: function(me, oOpts) {
console.log('focus');
},
show: function(me, oOpts) {
console.log('show');
},
}
});
As one can quickly see, I've tried testing all kinds of events. However only the activate event seems to fire -at page load-. What am I doing wrong? I'm not fully seeing which of the many events would be useful (see here)
You may want to listen for the tabchange(tabPanel, newCard, oldCard, eOpts) event on the tabpanel, and then fire your own event on the newCard (and maybe a different one on the oldCard).
I realize this is a very old question with an answer already. But I hope for future people (like myself) who find this, here is another perspective.
The "activate" event is fired on the tab itself when it is activated.
See documentation:
https://docs.sencha.com/extjs/6.5.2/classic/Ext.container.Container.html#event-activate
It doesn't work in your example most likely because you've nested (unnecessarily?) the "OrderContainer" inside another panel called "Home". Home receives the "activate" event correctly every time the user opens the tab, but its' children (like OrderContainer, who is doing the listening) do not.
So my suggestions are either:
Rearrange your logic so the "home" component is the one who is listening to the "activate" event and doing whatever loading you want to do.
Remove the "Home" panel entirely, and just use the orderContainer directly.
If you only have the "Home" there to provide a title and icon, you can add those to OrderContainer instead via tabConfig property:
items: [
{
xtype: 'ordercontainer'
tabConfig: {
title: 'Home',
iconCls: 'x-fa fa-home'
}
}
]
i have strange issue with removing item from fieldset. my app success adding new textfield fieldset item, buth when i do remove() my app screen got stuck without any error on my google chrome.
here my source
view js
Ext.define('qms.view.QC23', {
extend: 'Ext.form.FormPanel',
alias: 'widget.QC23View',
id: 'QC23View',
requires: ['Ext.form.FieldSet', 'Ext.Label'],
config: {
items: [
{
xtype: 'fieldset',
//defaults: { labelAlign: 'top' },
Id:'defectAdd',
layout:{
},
items: [
{
xtype: 'button',
text: 'New Defect',
id: 'DefectQC23Button',
ui: 'action'
},
{
xtype: 'button',
text: 'Remove Defect',
id: 'RemoveQC23Button',
ui: 'action'
}
]
}
]
}
and my controler
Ext.define('qms.controller.QC23con', {
extend: 'Ext.app.Controller',
config: {
refs: {
addDefectButton:'#DefectQC23Button',
rmDefectButton:'#RemoveQC23Button'
},
control: {
addDefectButton:{
tap: 'addDefect'
},
rmDefectButton:{
tap: 'removeDefect'
},
}
},
addDefect: function(button){
button.up('fieldset').add({
xtype: 'textfield',
name: 'MyField-' + button.up('fieldset').length
});
//Ext.getCmp('defectAdd').doLayout();
},
removeDefect: function(button){
button.up('fieldset').remove(button.up('fieldset').items.items[0]);
}
the function for adding item work fine, but when i remove the item my screen stuck. i am using google chrome for testing.
please give me solution for this issue.
thanks.
I noticed you are not checking for the xtype before removing an item from the fieldset. The code might be removing the button itself in which case it might cause your screen to freeze. I created a simple sencha fiddle https://fiddle.sencha.com/#fiddle/4tf that does what you are trying to accomplish.
replace the removeDefect function with this:
var lastItem = button.up('fieldset').items.items.length-1;
if(button.up('fieldset').items.items[lastItem].xtype ==='textfield')
button.up('fieldset').remove(button.up('fieldset').items.items[lastItem]);
I have some trouble using an Ext.Panel in Sencha Touch 2.2. It works at first, but after building it can't be closed though hideOnMaskTap is true.
Here's my code:
MinPanel.js
Ext.define('MinimalPanelExample.view.MinPanel', {
extend: 'Ext.Panel',
requires: [
'Ext.dataview.List'
],
config: {
id: 'minPanel',
width: '320px',
height: '480px',
modal: true,
hideOnMaskTap: true,
html: 'minimal panel',
items: [
{
xtype: 'list',
width: '100%',
height: '100%'
}
]
}
});
Adding it in Main.js:
var minPanel = Ext.create('MinimalPanelExample.view.MinPanel');
[...]
items: {
docked: 'top',
xtype: 'titlebar',
title: 'Welcome to Sencha Touch 2',
items: [
{
xtype: 'button',
text: 'Button',
listeners: {
tap: function(button) {
minPanel.showBy(button);
}
}
}
],
},
What's curious is that the list inside the panel isn't even shown if I run the built package, it just shows the html: 'minimal panel'. There's no warnings in the Javascript console, though.
Any ideas about why that happens?
Also, feel free to tell me if my way of creating / accessing the panel in the first place is wrong.
Figured it out. You can't just Ext.create on top of the Main view file, it has to be somewhere in the Ext.define block. It works if I create the MinPanel in an initialize listener, and then get it via Ext.getCmp('minPanel') when the user presses the button.