I'm trying to follow the tutorial of extjs about adding a form on click.
Now the "twist" is that I directly wish to create a more structured approach. So I'm using Ext.define to create both a grid and a form, for the grid.
The grid:
Ext.define('MyApp.view.main.EmployeeGrid', {
extend: 'Ext.grid.Grid',
xtype: 'employee-grid',
title: 'Employee Directory',
iconCls: 'x-fa fa-users',
listeners: {
itemtap: function() {
console.log("test");
Ext.create("MyApp.view.main.FormPanel", {});
}
},
store: {
data: [{
"firstName": "Jean",
"lastName": "Grey",
"phoneNumber": "(372) 792-6728"
}]
},
columns: [{
text: 'First Name',
dataIndex: 'firstName',
flex: 1
}, {
text: 'Last Name',
dataIndex: 'lastName',
flex: 1
}, {
text: 'Phone Number',
dataIndex: 'phoneNumber',
flex: 1
}]
});
the form:
Ext.define("MyApp.view.main.FormPanel", {
extend: "Ext.form.Panel",
xtype: 'form-panel',
title: 'Update Record',
floating: true,
centered: true,
width: 300,
modal: true,
items: [{
xtype: 'textfield',
name: 'firstname',
label: 'First Name'
}, {
xtype: 'toolbar',
docked: 'bottom',
items: ['->', {
xtype: 'button',
text: 'Submit',
iconCls: 'x-fa fa-check',
handler: function() {
this.up('formpanel').destroy();
}
}, {
xtype: 'button',
text: 'Cancel',
iconCls: 'x-fa fa-close',
handler: function() {
this.up('formpanel').destroy();
}
}]
}]
});
The problematic code is under the listeners: ... in the MyApp.view.main.EmployeeGrid class. The console is entry is logged, so I know the function is executed. However no form is shown. - What is the correct approach here?
Yes, as you said, no form is shown, because a newly created form is not shown by default.
Two solutions:
You can add to the form autoShow: true OR
You can add execute the show function on the created form: Ext.create(...).show()
However, I would recommend that you reuse the form, so instantiate a new one only once, store it on your grid, and reuse it for subsequent calls:
itemtap: function(view, index, target, record) {
if(!this.myForm) this.myForm = Ext.create("Ext.form.Panel", {});
this.myForm.loadRecord(record);
this.myForm.show();
}
For this to work, you may have to set closeAction: 'hide' on the form.
In at least some versions of ExtJS 6, it seemed to me as if IE exhibited memory leaks on component instantiation, so one should create as few new components as possible.
Related
I have the following code in ExtJS
var formPanel = Ext.create('Ext.form.Panel', {
title: 'Panel title',
renderTo: Ext.getBody(),
items: [{
xtype: 'container',
layout: 'hbox',
items: [{
xtype: 'textfield',
fieldLabel: 'First Name',
name: 'FirstName',
}, {
xtype: 'textfield',
fieldLabel: 'Last Name',
name: 'LastName',
},{
xtype:'fieldset',
title: 'Phone Number',
defaultType: 'textfield',
items :[{
fieldLabel: 'Home',
name: 'home',
value: '(888) 555-1212'
},{
fieldLabel: 'Business',
name: 'business',
toBeRendered: IS_BUSINESS_FIELD_SUPPORTED_IN_CURRENT_RELEASE // custom property that must restrict rendering
rendered: IS_BUSINESS_FIELD_SUPPORTED_IN_CURRENT_RELEASE //doesn't work
}]
}]
}]
});
I want to create an application, that will have properties file where I can set up flags for SUPPORTED fields e.g IS_BUSINESS_FIELD_SUPPORTED_IN_CURRENT_RELEASE = false. If it's false than text input fieldLabel: 'Business' will not be rendered at all - no hidden/disabled text input Business in html.
I've tried rendered property - but it doesn't work, the only solution so far is to use items = Ext.Array.filter(items,filterFunction) in onRender;
Are there any other solutions how can I restrict rendering input elements?
Thanks in advance.
Instead of the constructor, use the initItems method:
Ext.define('MyComponent', {
extend: 'Ext.panel.Panel',
xtype: 'mycomponent',
bodyPadding: 10,
border: true,
title: 'My component',
items : [
{
xtype: 'button',
text: 'My allowed button'
}
],
initItems : function() {
var items = this.items;
// Your conditions
if (false) {
items.push({
xtype: 'button',
text: 'My denied button'
});
}
this.callParent();
}
});
https://fiddle.sencha.com/#fiddle/17qi
I think that best approach is to define custom components for your application parts and add required components within its constructor, like this:
constructor: function () {
var myComponentItems = [
{
xtype: 'button',
text: 'My allowed button'
}
];
// Your conditions
if(false) {
myComponentItems.push({
xtype: 'button',
text: 'My denied button'
});
}
Ext.apply(this, {
items: myComponentItems
});
this.callParent(arguments);
}
Working fiddle
As I am a newbie to Ext JS and Sencha Architect, I am a but struggling here :(
I have one grid whihc shows two columns ID and Name as follow
ID | Name
1000 CA
1001 TX
1002 VA
There are two buttons Add & Update.
Code of the grid is as follow:
items: [
{
xtype: 'panel',
scrollable: true,
title: 'Plant',
dockedItems: [
{
xtype: 'gridpanel',
buttons: [
{
text: 'Add Plant',
handler: function() {
});
}
},
{
text: 'Update Plant',
handler: function() {
Ext.create('XYZ.view.UpdatePlantWindow', {
title: 'Update Plant'});}
}
],
buttonAlign: 'center',
dock: 'top',
id: 'PlantGrid',
scrollable: true,
store: 'PlantStoreAdmin',
columns: [
{
xtype: 'gridcolumn',
dataIndex: 'ID_PLANT',
text: 'Plant ID'
},
{
xtype: 'gridcolumn',
dataIndex: 'DS_PLANT',
text: 'Plant Name',
flex: 1
},
Now when user selects any row and clicks on Update Button, new window opens which has two text fields ID and Name. I want to populate these two fields with appropriate values that user has selected in the grid.
Code of windows:
Ext.define('XYZ.view.UpdatePlantWindow', {
extend: 'Ext.window.Window',
alias: 'widget.updateplantwindow',
requires: [
'Cepheid.view.UpdatePlantWindowViewModel',
'Ext.container.Container',
'Ext.form.field.Text'
],
viewModel: {
type: 'updateplantwindow'
},
autoShow: true,
height: 250,
width: 400,
title: 'Update Plant',
items: [
{
xtype: 'container'
},
{
xtype: 'textfield',
disabled: true,
id: 'PlantIDUpdate',
fieldLabel: 'Plant ID'
},
{
xtype: 'textfield',
fieldLabel: 'Label',
id: 'PlantNameUpdate'
}
]
});
Now how do I populate both the text fields with appropriate values?
Thanks in advance !
You can use the SelectionModel to get the currently selected record(s) in the grid. ie:
var selection = myGrid.getSelectionModel().getSelection();
And i'd recommend wrapping the fields in your window in a form because then you could use the loadRecord method to push the selection values to the form.
ie.
myWindow.down('form').getForm().loadRecord(selection[0]);
otherwise, if you don't want to wrap in the form you could load each individual value on the window:
myWindow.down('#myField').setValue(selection[0].get('my_value'));
Here is a fiddle demonstrating a working example
I have a nested list in my application, and when users make a selection they are taken to a detailCard with some options. One of these options is to "confirm" their selection. Once confirmed, the selection should be removed from the list. This works on the server side, so if the app is refreshed the selection is gone. However I was hoping to remove the selection in the treeStore itself and refresh the view somehow so that users can immediately see the effect of their confirmation. I was following a tutorial for nestedList that I can't seem to find anymore, and this code is based on that:
var itemId = '';
Ext.define('MyApp.view.MainView',
{
extend: 'Ext.tab.Panel',
xtype: 'main',
alias: "widget.mainview",
requires: [
'Ext.dataview.NestedList',
'Ext.data.proxy.JsonP'
],
config:
{
tabBarPosition: 'bottom',
items: [
{
xtype: 'nestedlist',
title: 'Listings',
iconCls: 'home',
displayField: 'listingValue',
scrollable: true,
detailCard:
{
xtype: 'panel',
scrollable: true,
styleHtmlContent: true,
items: [
{
xtype: 'fieldset',
readOnly: true,
title: 'Schedule Information:',
items: [
{
name: 'from',
id: 'from',
xtype: 'textareafield',
label: 'From',
readOnly: true
},
{
name: 'to',
id: 'to',
xtype: 'textareafield',
label: 'To',
readOnly: true
},
{
name: 'moreInfo',
id: 'moreinfo',
xtype: 'textfield',
label: 'More Info',
readOnly: true
},
]
},
{
xtype: 'container',
flex: 1,
items: [
{
xtype: 'button',
text: 'Confirm',
action: 'confirmSelection',
margin: '10 5',
padding: '5',
ui: 'confirm'
}]
}]
},
listeners:
{
itemtap: function (nestedList, list, index,
element, post)
{
var detailCard = this.getDetailCard();
detailCard.setHtml('');
itemId = post.get('id');
Ext.getCmp('from').setValue(post.get(
'from'));
Ext.getCmp('to').setValue(post.get('to'));
Ext.getCmp('moreinfo').setValue(post.get(
'moreinfo'));
}
},
store:
{
type: 'tree',
fields: [
'id', 'from', 'to', 'fromcity', 'tocity',
'time', 'address',
{
name: 'leaf',
defaultValue: true
},
{
name: 'listingValue',
convert: function (value, record)
{
listingValue = '$<b>' + record.get(
'address') + '</b> ' + record
.get('fromcity') + ' to ' +
record.get('tocity');
return listingValue;
}
}
],
root:
{
leaf: false
},
proxy:
{
type: 'jsonp',
url: 'http://myURL.com/page.php?action=go',
reader:
{
type: 'json',
rootProperty: 'root'
}
}
}
},
{
title: 'Dashboard',
iconCls: 'action',
items: [
{
docked: 'top',
xtype: 'titlebar',
title: 'Dashboard'
},
]
}]
}
});
I have no idea what to do at this point, because the store is set up in the view and I'm not sure how to access it in my controller. I learned about treeStore.removeAll() and treeStore.load(), but how can I call those functions in a controller when the store is set up without any type of reference name? Is there a way I can remove the user's selection and display the view, or perhaps reload the view altogether so it can retrieve the new list from the server?
Because my list is on the first page of my app, I managed to get away with window.location.reload(); and reloading the whole app. Its not the most elegant solution, but the changes are reflected.
I won't accept my own answer just yet in case someone comes along with a better solution.
I'm trying to read a property from my custom panel for using it into a property item from the same panel. Let me show my code so you can understand what I mean:
Ext.define('XXX.XXX.XXX.MyPanel', {
extend: 'Ext.panel.Panel',
title: 'My Panel',
autoScroll: true,
isMyProperty: false,
defaults: {
margin: 4,
xtype: 'horizontalfieldpanel'
},
items: [
{
title: 'SOme title',
itemId: 'title1',
items: [
{
xtype: 'textfield',
name: 'name',
fieldLabel: 'Name',
allowBlank: !this.isMyProperty
}, {
xtype: 'textfield',
name: 'lastName',
fieldLabel: 'Last Name',
allowBlank: !this.isMyProperty
}, {
As you can see I have isMyProperty and I'm trying to use it on allowBlank, but it is not taking it. it is taking the value for default.
Any idea what I'm doing wrong?
Thanks,
The conventional way is to use the 'config' subsystem. This tells it to add a new configuration option to your class which also generates a getter/setter method for it.
The configuration option can be overridden when the panel is constructed just like any other config option in the base class.
One trick is that your items must then be constructed in the initComponent method as opposed to doing it in the class definition. I've found that in sophisticated applications, it's better to plan on overriding initComponent to create your items instead of using "static" item declarations in most situations.
Ext.define('XXX.XXX.XXX.MyPanel', {
extend: 'Ext.panel.Panel',
config: {
isMyProperty: false
},
title: 'My Panel',
autoScroll: true,
defaults: {
margin: 4,
xtype: 'horizontalfieldpanel'
},
initComponent: function() {
this.items = [{
title: 'Some title',
itemId: 'title1',
items: [{
xtype: 'textfield',
name: 'name',
fieldLabel: 'Name',
allowBlank: !this.#getIsMyProperty()
}, {
xtype: 'textfield',
name: 'lastName',
fieldLabel: 'Last Name',
allowBlank: !this.#getIsMyProperty()
}, {
...
}]
}];
this.callParent(arguments);
}
});
To override the value at construction:
var panel = Ext.create('XXX.XXXX.XXXX.MyPanel', {
isMyProperty: true
});
i have a tab-panel which works fine so far,
but as soon as i apply a grid-panel as one of the tabs i'm getting a js-error somewhere in Observerable.js (a class from ext) that say that 'item.on(...)' is not a function after 'item is undefinded'
Here are the appropriate code lines:
This is what i do in my tab panel:
initComponent: function() {
this.items = [{
xtype: 'profileList',
title: 'Profiles'
}];
this.callParent(arguments);
}
and here is how the code of my grid panel:
Ext.define('BC.view.profile.ProfileList', {
extend: 'Ext.grid.Panel',
alias: 'widget.profileList',
cls: 'profileList',
border: false,
initComponent: function(){
Ext.apply(this, {
store: 'Profiles',
columns: [{
text: 'Name',
dataIndex: 'name',
flex: 1,
}, {
text: 'Others',
dataIndex: 'otherUsers',
width: 200
}, {
text: 'Limit',
dataIndex: 'limit',
width: 200
}]
});
console.log('before');
this.callParent(arguments);
console.log('after');
}
});
Thanks for any help!
Edit: the first console.log works, the error seems to happen in 'callParent()'
You cannot create the items of the tab panel like that:
this.items = [{
xtype: 'profileList',
title: 'Profiles'
}];
You should use Ext.apply(... instead:
Ext.apply(this,{items:[{
xtype: 'profileList',
title: 'Profiles'
}]);