How can I query multiple components in Ext? - javascript

In my app, I have two pagingtoolbar in two views (separate files), how can I query them both in the controller?
dockedItems: [{
xtype: 'pagingtoolbar',
store: 'User',
dock: 'bottom',
displayInfo: true
}]
bbar: {
xtype: 'pagingtoolbar',
store: this.store,
displayInfo: true
}

Just adding to Alex Tokarev's answer, if you want to select them at run time, lets say, when you click on a button, you can use:
...
handler : function () {
var mytoolbars = Ext.ComponentQuery.query('pagingtoolbar'); // will assign all available toolbars to your mytoolbars array.
}
....

Controllers use ComponentQuery and their selectors are global, so just xtype should work:
Ext.define('MyController', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
pagingtoolbar: {
...
}
});
}
});

Related

ExtJS Modern - What initialization function to implement when extending a component

In ExtJS 6.2 classic we usually implement initComponent when we extend a component.
On ExtJS modern, there's no initComponent for Ext.Container, besides constructor which function would replace initComponent in Modern?
I'm having an issue because I implemented the component initialization in the constructor and when I display the component again it runs the constructor again with the config set as the previous updated config, so the component renders things multiple times where it should only render once.
Ext.define('AppName.view.settings.CalloutBox', {
extend: 'Ext.Container',
xtype: 'calloutbox',
layout : {
type : 'hbox',
},
constructor: function(config) {
// Added this to avoid the bug I commented above.
if (config.cls) {
this.callParent(arguments);
return;
}
config.cls = `myclass`;
// Here I programmatically add elements. These cause the bug
// because on next run of this constructor these will be
// added again.
config.items = [{
xtype : 'container',
cls : `alert__icon-box`,
layout: {
type : 'vbox',
pack : 'center',
align : 'middle'
},
items: [{
xtype :'label',
cls : `alert__icon`,
html : `<i class="x-font-icon md-icon-alert"></i>`,
}]
}];
this.callParent(arguments);
}
});
Update
I found out the cause of the duplicating elements bug. It was caused by recreating the modal that the CalloutBox was in every time instead of just showing the one already open.
So we had this:
Ext.Viewport.add({ xtype: 'mymodal' }).show();
And now:
const mymodal = Ext.getCmp('mymodal');
// If component already exists in DOM, just show it.
if (mymodal) {
mymodal.show();
return;
}
// Else we create and show it.
Ext.Viewport.add({ xtype: 'mymodal' }).show();
Check out the initialize template method of Container and other classes in Modern Toolkit. Try running the following code in a fiddle:
Ext.define('MyContainer', {
extend: 'Ext.Container',
xtype: 'mycontainer',
initialize: function () {
this.add({
xtype: 'container',
layout: {
type: 'vbox',
pack: 'center',
align: 'middle'
},
items: [{
xtype: 'label',
html: 'label1',
},{
xtype: 'label',
html: 'label2',
}]});
}
});
Ext.create({
"xtype": "mycontainer",
renderTo: Ext.getBody()
});

Problems with references and stores in Sencha ExtJS

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

I have a component define by itemid how I can get it in controller

i m new in sencha . i always use id to define my component . but now i want to change it to itemid . and i found the Ext.getcmp('id'), is not work . and when i use Ext.componentquery.query('itemid') ,the console in chrome said Ext.componentquery is not a function. what can i do?
my view code:
Ext.define('ylp2p.view.Main', {
extend: 'Ext.tab.Panel',
xtype: 'main',
requires: [
'Ext.TitleBar',
'Ext.carousel.Carousel',
'ylp2p.store.datainterests',
'Ext.Label',
'Ext.List'
],
config: {
fullscreen: true,
tabBarPosition: 'bottom',
scrollable: 'vertical',
items: [
{
title: '首页',
iconCls: 'home',
styleHtmlContent: true,
//true to automatically style the HTML inside the content target of this component (body for panels).
scrollable: true,
layout: 'card',
items: [
{
docked: 'top',
xtype: 'titlebar',
title: 'ylp2p'
},
{
xtype: 'container',
layout: 'vbox',
items:[
{
xtype: 'label',
itemId: 'datalabel',---------this component is what i want
height: 50,
store: 'datainterests',
tpl: '金额:{data},利息:{earn}',
}//end label
]
}
]//end items
}
]
},//end config
//end listeners
});
my controller code :
Ext.define('ylp2p.controller.viewdata',{
extend: 'Ext.app.Controller',
launch: function(){
console.log('hello ! here is controller launch function');
var storeId = Ext.create('ylp2p.store.datainterests');
storeId.load({
callback: function(records, operation, success){
Ext.each(records, function(record) {
Ext.ComponentQuery.query("main > datalabel").setData({----it cant work . why?
data : record.get('data'),
earn : record.get('earn')
});
});
}
});
}
});
the console error said:
Uncaught TypeError: Ext.ComponentQuery.query(...).setData is not a function
i got it
var label = Ext.ComponentQuery.query('main #datalabel')[0];
label.setData({
data : record.get('data'),
earn : record.get('earn')
});
I found Sencha's own code to use menu.down('#groupMenuItem') to access itemId:'groupMenuItem'. So you should be fine using:
Ext.ComponentQuery.query('#itemid')
Use this.
var label = Ext.ComponentQuery.query('main #datalabel'); -- check on console label should not undefined
label.tpl.updateData -- you will find methods with tpl

Loading different views for different profiles

I'm not sure I understand how to use profile views within a Sencha Touch 2 app.
Ext.define(App.view.phone.PhonePanel, {
extend: 'Ext.tab.Panel',
xtype: 'Compare'
config: {
items: [
{ xtype: 'PanelA' },
{ xtype: 'Panel B' }
]
}
})
Ext.define(App.view.tablet.TabletPanel, {
extend: 'Ext.Panel',
xtype: 'Compare'
config: {
layout: 'vbox',
items: [
{ xtype: 'PanelA', flex: 1 },
{ xtype: 'Panel B', flex: 1 }
]
}
})
And then within the Phone Profile, it adds "PhonePanel" as a view, and the Tablet profile adds "TabletPanel"; and then when that specific profile is loaded it only loads those additional views.
The problem I'm having is that Sencha is loading files from both profiles, and doing
this.getAview().push({xtype:'Compare'});
While the phone profile is active, it actually pushes the Tablet's version of the xtype. What is going on here?
These are the different steps to create profiles in a Sencha Touch 2 application :
Create app/profile/Base.js containing the following code
You're more likely to need a base profile if you execute the same code at the launch of the app for both the profiles. So this step is mandatory
Ext.define('App.profile.Base', {
extend: 'Ext.app.Profile',
launch: function () {
/* Custom Code */
Ext.fly('booting').destroy();
}
});
Create app/profile/Phone.js containing the following code
If you chose to go without the base controller, then be sure to extend Ext.app.Profile instead of App.profile.Base :
Ext.define('App.profile.Phone', {
extend: 'App.profile.Base',
config: {
controllers: ['Main'],
views: ['Main']
},
isActive: function() {
return Ext.os.is.Phone;
},
launch: function() {
Ext.create('App.view.phone.Main');
this.callParent();
}
});
Create app/profile/Tablet.js containing the following code
If you chose to go without the base controller, then be sure to extend Ext.app.Profile instead of App.profile.Base :
Ext.define('App.profile.Tablet', {
extend: 'App.profile.Base',
config: {
controllers: ['Main'],
views: ['Main']
},
isActive: function() {
return Ext.os.is.Tablet || Ext.os.is.Desktop;
},
launch: function() {
Ext.create('App.view.tablet.Main');
this.callParent();
}
});
Create app/view/phone/Main.js containing the following code
Ext.define('App.view.phone.Main', {
extend: 'Ext.Container',
config: {
fullscreen: true,
items: [{
html:'This is the main view for the phone profile'
}]
}
});
Create app/view/tablet/Main.js containing the following code
Ext.define('App.view.tablet.Main', {
extend: 'Ext.Container',
config: {
fullscreen: true,
items: [{
html:'This is the main view for the tablet profile'
}]
}
});
That's it. You should be all set.
Hope this helped
You are using the same xtype twice.
Think of an xtype as a short name for your component. Each component needs to have a unique shortname or it will just get overwritten by the more recent definition.
Change the above two components to something like xtype: 'tabletcompare' and xtype: 'phonecompare'.
AND
this.getAview().push({xtype:'tabletcompare'}) <br>
Or
this.getAview().push({xtype:'phonecompare'})
when referencing the objects.
Hope this helps!

Sencha Touch: Dynamically change Stores with one List

So, I'm trying to write a little MVC application which uses lists a lot.
I have one view which consists of a Panel with Toolbar docked to top and List:
app.views.SalonListView = Ext.extend(Ext.Panel, {
layout: 'card',
cardSwitchAnimation: 'slide',
dockedItems: [
{
xtype: 'toolbar',
dock: 'top'
}
],
items: [
{
xtype: 'SalonList',
id: 'salon-list'
}
]
});
Ext.reg('ListView', app.views.SalonListView);
I have an xtype for list defined in another file:
app.views.SalonList = Ext.extend(Ext.List, {
layout: 'card',
itemTpl: // some tpl is here
});
Ext.reg('SalonList', app.views.SalonList);
As you may notice, I don't set the Store for my List.
What am I trying to achieve is to set store in any Controller I use with this view.
Something like:
salonList: function() {
app.stores.SalonStore.read();
this.salonsView = this.render({
xtype: 'SalonListView',
// so I need to set store for the list somewhere around here
});
}
Is there any possibility I can set the Store for the List dynamically?

Categories

Resources