Can I change property of panel dynamically in Ext JS? - extjs

So I have a following View that extends the Ext.panel.Panel
Ext.define('SomeView', {
extend: 'Ext.panel.Panel',
alias: 'someview',
title: 'Some View',
closable: true,
initComponent: function () {
this.itemId = 'someView';
this.callParent(arguments);
},
layout: {
type: 'vbox',
align: 'stretch'
},
items: [
{
xtype: 'container',
layout: 'hbox',
items: [
{
xtype: 'container',
itemId: 'someContainer',
tpl: '<h2>{someProperty}</h2>',
flex: 1
},
// other code omitted for brevity
});
I initialize the view like this.
var panel = Ext.create('someview', {
someProperty: 'Some Value'
});
After the view is shown the parameter that I pass to someProperty is shown as well. But the thing is, I want to change someProperty after the view is shown. Can I do that? and if yes, how ? I mean I can change it like this
panel.someProperty = 'Some New Value';
but the view does not get effected itself.

You will want to add a member function to your panel class to do the actual work of updating what is shown on the screen:
setSomeProperty: function(prop) {
this.down('#someContainer').update({someProperty: prop});
}

Related

EXTJS adds the row to the top of the container on the .insert()

I am using an EXTJS xtype: container to create a row and when I want to insert a row into the store the row gets added to the top of the existing row instead of the bottom, is there any way to add the newly created row to the bottom?
Below is the code:
somefunc: function (token, filter, op) {
var filter = Ext.create({
xtype: 'container',
height: 30,
cls: 'purge-filter-item',
layout: {
type: 'hbox',
align: 'middle'
},
items: [
this.typeCombo = new Ext.form.ComboBox({
emptyText: $L('Select a filter...'),
store: this.menuStore = new Ext.data.ArrayStore({
fields: ['key', 'title'],
data: this.getFilterValues()
})
})
]
});
this.insert(0, filter);
this.doLayout();
return filter;
}
Any idea why this could be happening and how to fix this?
Any idea why this could be happening and how to fix this?
Because you are using insert() method instead of this you can use add() method it will by default add in last index.
In this FIDDLE, I have created a demo using add() method to adding new component. I hope this will help/guide you to achieve your requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create('Ext.panel.Panel', {
title: 'Add new row',
renderTo: Ext.getBody(),
tbar: [{
text: 'Add new',
handler: function (btn) {
var panel = btn.up('panel');
panel.add({
xtype: 'container',
height: 30,
cls: 'purge-filter-item',
layout: {
type: 'hbox',
align: 'middle'
},
items: [{
xtype: 'textfield',
emptyText:'enter value here',
fieldLabel:'this is field '+( panel.items.items.length+1)
}]
});
}
}]
})
}
});

How to Abstract a base container with some default items in Sencha Extjs 6?

I was trying to develop a base container by extending Ext.Container, which have some default items in it. A subclass should add the items to the child component of the base class and not directly to the container instead. How to do this?
May i override the setItems/applyItems method to add the items to navigationView.add(items); ?? I'm unsure about how this works. Since i'm new to ExtJs, unable to identify which is the way to do it generically so that it won't affect my subclass to add n number of items to it either using inline or add(item) method.
AbstractClass
Ext.define('MyApp.container.AbstractMainContainer', {
extend: 'Ext.Container',
xtype: 'abstractmaincontainer',
requires: [
'MyApp.container.NavigationView',
'MyApp.control.NavigationBar'
],
config: {
layout: {
type: 'vbox',
pack: 'start',
align: 'stretch'
},
flex: 1,
height: '100%',
width: '100%'
},
controller: 'maincontroller',
items: [{
xtype: 'navbar',
itemId: 'navbar'
}, {
xtype: 'navigationview',
itemId: 'navigationview',
reference: 'navigationview',
navigationBar: false,
layout: {
pack: 'start',
align: 'stretch'
},
flex: 1,
height: '100%',
items: [
// new item should added here
]
}],
/**
* #method getContentView add the items to this rather than directly
* #return {void}
*/
getContentView: function() {
return this.down('#navigationview');
},
});
SubClass
Ext.define('MyApp.main.view.MainContainer', {
extend: 'MyApp.container.AbstractMainContainer',
requires: [
'MyApp.container.AbstractMainContainer'
],
config: {
},
items: [{
// we should not directly add items here this will remove the navbar and navigation view
// HOW TO ADD THIS IN A GENERIC WAY??
xtype: 'container',
layout:{
type:'card'
},
items: [{
xtype: 'button',
role: 'nav',
title: 'Card 1',
text: 'go to next',
handler: function() {
}
}, {
itemId: 'myCard',
title: 'Card 2',
html: '<h1>Card 2</h1>'
}],
}],
});
AFAIK, there's no "automatic" way to do it.
I can suggest some approaches:
First of all, check if you really need to do this: for example, you could move the navbar to the dockedItems config and move the navigationview one level up.
So your AbstractContainer will extend navigationview, navbar will be a dockedItem, and you will be able to use the items config as usual.
Otherwise, you could use a different config (let's say "extraItems" or "navItems"), and merge them overriding the abstract class initComponent function.
There, after a callParent that actually initialize the navigationview, you could do something like
this.down('navigationview').add(this.extraItems);

Run same code in each tab in extjs

I wish to have the same form panel in each tab of the tabbed pannel. Is there a way that the same code is run for each tab without having to copy the code in the items list since that would be redundant.
Here is one way to do it -
You'll normally define a tabpanel and you give multiple panels as an array of items. For each of the panel inside the item, give the same panel container that you define below as the item.
{
xtype: 'tabpanel',
itemId: 'myTabPanel',
activeTab: 0,
plain: true,
items: [{
xtype: 'panel',
itemId: 'tab1',
layout: 'fit',
title: 'Strategies',
items: [{
xtype: 'myTabContainer'
}],
tabConfig: {
xtype: 'tab',
closable: false
}
}, {
xtype: 'panel',
itemId: 'tab2',
layout: 'fit',
title: 'Action Sets',
items: [{
xtype: 'myTabContainer'
}]
}],
listeners: {
tabchange: 'tabChangeListener' // define this and handle the actions for your tab change event
}
}
And here is a sample definition of the container/content for the tab. You can note that I'm using the alias for this container "myTabContainer" as xtype in each of the tabs above. This will make sure that the same view is linked to both the tabs.
Ext.define('MyTabContainer', {
extend: 'Ext.panel.Panel',
alias: 'widget.myTabContainer',
requires: [
// give all required classes
],
viewModel: {
type: 'dfstrategiesmaincontainer'
},
itemId: 'tabContent',
layout: 'border'
// Define all other required items and contents
}
Define a form and set that form as an item in each tab.
//Define the form
Ext.define('App.view.MyForm', {
extend:'Ext.form.Panel',
alias: 'widget.myform',
bodyPadding:10,
items: [....]
});
//Use the form as an item in each tab
Ext.create('Ext.tab.Panel', {
width: 400,
height: 400,
renderTo: document.body,
items: [{
title: 'Tab1',
xtype: 'myform'
}, {
title: 'Tab2',
xtype: 'myform'
}]
});

Cannot get the object of a tabpanel

I have a grid in the center region of a border layout. When a specific item is clicked in the grid, I need to change the center region to display a tab panel. I am having trouble getting the tabpanel object.
In the ctrlpanel file, on the grid listener, I am using componentQuery to get the tabpanel('ccmain') object. It returns undefined.
I was using componentQuery to get 'ccmain' in the centerpanel file(lays out center region) successfully, but when I moved this code to the ctrlpanel file(one of the items in centerpanel) it fails. ComponentQuery no longer returns the tabpanel 'ccmain'. ComponentQuery does return the centerpanel or the viewport. I attemped to do centerpanel or viewport.down to find 'ccmain', but that also returns undefined. If you can tell me how to get the tabpanel or what I am doing wrong, I would appreciate it. Thanks for your time.
ctrlPanel.js
Ext.define('ServcSol.view.CtrlPanel',{
extend: 'Ext.Panel',
alias: 'widget.ctrlPanel',
xtype: 'ctrlPanel',
itemId: 'ctrlPanel',
requires:[
'ServcSol.store.FacilityStore'
],
initComponent: function () {
var me = this;
Ext.applyIf(me, {
items: [
{
xtype: 'panel',
height: 750,
title: 'Control Panel',
items: [
{
xtype: 'gridpanel',
padding: '20 20 5 20',
store: 'WorkHistoryStore',
height: 590,
width: '100%',
border: true,
columns: [
{
width: 110,
dataIndex: 'wrkhistDate',
text: 'Due Date'
},
{
width: 100,
dataIndex: 'wrkType',
text: 'Work Type'
}
],
listeners : {
itemclick: function(dv, record, item, index, e)
{
if(record.get('wrkType') == 'Test')
{
var tabPanel = Ext.ComponentQuery.query('ccmain')[0];
console.log('tabPanel is: ', tabPanel);
var tabIndex = tabPanel.items.findIndex('id', 'hazard');
var center = Ext.ComponentQuery.query('centerpanel')[0];
center.getLayout().setActiveTab(tabIndex);
}
ccmain.js
Ext.define('ServcSol.view.ccMain', {
extend: 'Ext.tab.Panel',
itemId: 'ccmain',
alias: 'widget.ccmain',
xtype: 'ccmain',
initComponent: function () {
var me = this;
Ext.applyIf(me, {
items: [
{
xtype: 'facility'
},
{
xtype: 'hazListing'
},
{
xtype: 'hazard'
},
{
xtype: 'testFormRP'
},
{
xtype: 'testFormDC'
}
]
});
this.callParent(arguments);
}
});
One of the reasons can be that ccmain is not instantiated as only instantiated components can be found by ComponentQuery.query. Then, even if ccmain would be found you cannot set its active item that way. Easiest is to assign tabs itemIds and then call setActiveTab:
tabPanel.setActiveTab(itemIdOfTheTab)

Cannot create an instance of unrecognized alias: widget.[object Object]

I have been trying to add a custom class into one of my views but when I run the application, I get an error in the console log "Cannot create an instance of unrecognized alias: widget.[object Object]". My code is as follows:
SubCategoryListView.js
Ext.define('RestaurantGlobal.view.SubCategoryListView',{
extend: 'Ext.List',
xtype: 'SubCategoryListView',
requires: ['RestaurantGlobal.store.ItemColumnsStore'],
config:{
items:[
{
xtype: Ext.create('Ext.List', {
fullscreen: true,
items: [{
xtype: 'toolbar',
docked: 'top',
ui: 'neutral',
items: [
{
text:'Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'False');
}
},
{
text:'Non-Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'True');
}
},
],
store: 'RestaurantGlobal.store.ItemColumnsStore',
itemTpl: ['{Name} {Image}']
}],
}),
}
]
}
});
SubCategories.js
Ext.define('RestaurantGlobal.view.SubCategories', {
extend: 'Ext.Panel',
requires : ['RestaurantGlobal.view.SubCategoryListView'],
config: {
styleHtmlCls: 'maincontainer',
styleHtmlContent: true,
layout: {
type: 'vbox'
},
items: [
{
xtype: 'titlebar',
flex: 0.5,
docked: 'top',
title: 'Category Name'
},
{
xtype: 'SubCategoryListView',
},
{
xtype: 'container',
items: [
{
xtype: 'button',
docked: 'bottom',
margin: '0 0 0 0',
text: 'Place Order'
}
]
}
]
}
});
Please help me in this regard. Also, is there a way to filter a single store to display them into 2 tabs in the same tabpanel?
I am not using tab panel in this case.
The culprit is this:
xtype: Ext.create('Ext.List', {
xtype must be a string.
You can theoritically put a component instance directly in the items:
items:[
Ext.create('Ext.List', {
fullscreen: true,
items: [{
xtype: 'toolbar',
docked: 'top',
ui: 'neutral',
items: [
{
text:'Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'False');
}
},
{
text:'Non-Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'True');
}
},
],
store: 'RestaurantGlobal.store.ItemColumnsStore',
itemTpl: ['{Name} {Image}']
}],
}
]
But in the context of a class definition that would really be ill inspired because this same component instance would be used by every instance you create of your class. Most probably resulting in a lot of problems...
In case you really need to create the component instance yourself, because you can't simply declare its configuration, do it by overriding the initComponent method, and create your component in there. The initComponent method will be called for each new instance of your class, so each one will have its own instance of the child component (sorry, I know that makes a lot of repetitions of the word "instance").
Anyway, it seems that what you are really trying to do is simply to override the list class:
Ext.define('RestaurantGlobal.view.SubCategoryListView',{
extend: 'Ext.List',
xtype: 'SubCategoryListView',
requires: ['RestaurantGlobal.store.ItemColumnsStore'],
// You class is already a list, just add your custom configuration
// directly to it:
config:{
fullscreen: true,
items: [{
xtype: 'toolbar',
docked: 'top',
ui: 'neutral',
items: [{
text:'Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'False');
}
},{
text:'Non-Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'True');
}
}],
store: 'RestaurantGlobal.store.ItemColumnsStore',
itemTpl: ['{Name} {Image}']
}]
}
});
Ext.define('RestaurantGlobal.view.SubCategoryListView',{
extend: 'Ext.List',
*xtype: 'SubCategoryListView',*
The problem is that you used xtype in class definition but it could be alias:
Ext.define('RestaurantGlobal.view.SubCategoryListView',{
extend: 'Ext.List',
alias: 'widget.SubCategoryListView',
and then you can use this class to create list in this case by:
xtype: 'SubCategoryListView'
as you expected.

Resources