Trouble with adding and removing ExtJS form fields - javascript

I am having a bit of trouble adding/removing fields to/from an ExtJS form. My use case is as follows:
Provide a set of radio buttons on the form. Depending on which radio button is selected, show a different set of form fields.
I am not all that familiar with ExtJS, but what I am doing is caching the fields that are to be added/removed and adding/removing them from the form when the radio button change event is fired. Here is a simplified version of my code:
var textFieldA = new Ext.form.TextField({
fieldLabel: 'Text Field A',
name: 'text_field_a',
allowBlank: false
});
var textFieldB = new Ext.form.TextField({
fieldLabel: 'Text Field B',
name: 'text_field_b',
allowBlank: false
});
var form = new Ext.FormPanel({
autoScroll: true,
bodyStyle: 'padding: 5px 5px 0',
border: false,
frame: true,
layout: 'form',
items: [{
xtype: 'fieldset',
fieldLabel: 'Fieldset',
autoHeight: true,
items: [{
xtype: 'radiogroup',
fieldLabel: 'Show text field',
columns: 1,
vertical: true,
items: [
{
xtype: 'radio',
boxLabel: 'Show field a',
name: 'field_to_show',
inputValue: 'a'
},
{
xtype: 'radio',
boxLabel: 'Show field b',
name: 'field_to_show',
inputValue: 'b'
}
],
listeners: {
'change': {
fn: function(radioGroup, selectedRadio) {
switch (selectedRadio.getGroupValue())
{
case 'a':
radioGroup.findParentByType('fieldset').remove(textFieldB);
radioGroup.findParentByType('fieldset').add(textFieldA);
break;
case 'b':
radioGroup.findParentByType('fieldset').remove(textFieldA);
radioGroup.findParentByType('fieldset').add(textFieldB);
break;
}
radioGroup.findParentByType('fieldset').doLayout();
}
}
}
}]
}]
});
form.render('container');
This works the first time each radio is selected, but subsequent selections do not work as I would expect. In Firefox, a JavaScript error is raised:
Operation is not supported" code: "9
[Break on this error] return !!(p.compareDocumentPosition(c) & 16); in ext-base-debug-w-comments.js
In Chrome, only the labels will be added to the form.
Is the way I am expecting this to work incorrect?

I wouldnt necessarily take the approach of adding/removing the fileds- why not give each field an id (also good practice for form fields) using:
id:'fieldname'
Then either hide/show the field as appropriate using:
Ext.getCmp('fieldname').hide()
Ext.getCmp('fieldname').show()

I've written a very similar form. If the only common element is the radio group, here's what I suggest:
Create an outer Container that contains the RadioGroup, then a subcontainer with a CardLayout. Each child of that card layout contains a form with the fields for the different states of the RadioGroup. Add listeners to the RadioGroup so when the selection changes, you change the active item in the card container.
Basic code to get you started from when I did this:
OuterForm = Ext.extend(Ext.Container, {
initComponent: function() {
Ext.apply(this, {
layout: "vbox",
layoutConfig: { align: "stretch" }
});
this.items = [{
xtype: "container",
layout: "form",
items: [{
xtype: "radiogroup",
fieldLabel: "Form to fill out",
ref: "../../formSelector",
items: [{
name: "type",
inputValue: "1",
boxLabel: "Form 1"
}, {
name: "type",
inputValue: "2",
boxLabel: "Form 2"
}],
listeners: {
scope: this,
change: function(rg, checkedItem) {
this.formContainer.layout.setActiveItem(parseInt(checkedItem.inputValue));
}
}
}]
}, {
xtype: "container",
layout: "card",
flex: 1,
ref: "formContainer",
items: [{
xtype: "form1"
}, {
xtype: "form2"
}]
}];
OuterForm.superclass.initComponent.call(this);
}
});
Not tested for typos/bugs, but just set a height for the outer form, create your form1 and form2 xtypes and it should work.
If you need all fields part of the same form, make OuterForm extend FormPanel instead of defining form1 and form2 as independent FormPanels.

Related

Focus a textfield inside a list

The ExtJS docs describe a method focus for textfields that will either focus a textfield or return false: https://docs.sencha.com/extjs/6.7.0/modern/Ext.field.Text.html#method-focus
Generally this seems to work just fine, but once the textfield that should be focused is inside a list (part of the listitem) the focus is immediately removed and set to the parent listitem container. Focus however returns true (the focus is actually on the field for a few ms).
https://fiddle.sencha.com/#view/editor&fiddle/315h shows this by example. The first button tries to focus the first textfield inside the list (which fails) and the second one focuses the field below the list.
Is there any way to prevent the listitem from becoming focused?
Code from the fiddle:
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create({
fullscreen: true,
xtype: 'container',
items: [{
xtype: 'list',
itemConfig: {
xtype: 'container',
items: [{
xtype: 'component',
html: 'Row'
}, {
xtype: 'textfield',
value: 'Focus Me'
}],
margin: '15px 0'
},
data: [{
title: 'Item 1'
}, {
title: 'Item 2'
}, {
title: 'Item 3'
}, {
title: 'Item 4'
}]
}, {
xtype: 'button',
text: 'Try to focus',
handler: function () {
this.up('container').down('list').down('textfield').focus();
Ext.toast(this.up('container').down('list').down('textfield').hasFocus + '');
}
}, {
xtype: 'textfield',
itemId: 'focusable',
value: 'Focusable'
}, {
xtype: 'button',
text: 'Try to focus',
handler: function () {
this.up('container').down('#focusable').focus();
Ext.toast(this.up('container').down('#focusable').hasFocus + '');
}
}]
});
}
});
On ExtJS 6.7 the first click on a textfield in a list does not even work but this seems to be fixed in 7.0.
Set defaultFocus for listitem container. Its work for me (fiddle).
P.S. thank you for your fiddle example. few do it.

How to add a fieldset in EXTJS on button click

My problem is when I click Add button it needs to add a fieldset ("rulepanel") after the previous fieldset, but in my code if I execute it the new fieldset is added on top of the previous (I can be able to notice it as the letters are getting bold when click on Add button).
This is my code:
var rulepanel = {
xtype: 'fieldset',
border: false,
itemId: 'rule',
items: [{
xtype: 'container',
items: [{
xtype: 'textfield',
fieldLabel: 'value',
name: 'value',
allowBlank: false,
placeholder: 'value'
}, {
xtype: 'button',
id: 'add',
text: 'Add',
handler: function (button, event) {
me.insert(rulepanel);
}
}, {
xtype: 'button',
id: 'branch',
text: 'Branch'
}]
}]
};
Ext.apply(me, {
items: [rulepanel]
});
Your code should be like below:-
{
xtype: 'button',
text: 'Add',
handler: function (button, event) {
button.up('fieldset').insert(rulepanel);
}
}
You can find running example here.
Hope this will help you.

How to get values of multiple textfields with same name in extjs2

I am adding a textfield dynamically when i click add button, after that i need to get the values what i added dynamically while i click save button. its in extjs2.0 itself.
This is the code what i am working on
var settingsEmailPanel = new Ext.FormPanel({
labelWidth: 75, // label settings here cascade unless overridden
url:'save-form.php',
frame:true,
id:'emailForm',
title: 'Email Servers',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {width: 230},
defaultType: 'checkbox',
items: [{
boxLabel: 'Server 1',
hideLabel: true,
name: 'server1'
},{
boxLabel: 'Server 2',
hideLabel: true,
name: 'server2'
},{
boxLabel: 'Server 3',
hideLabel: true,
name: 'server3'
}, {
boxLabel: 'Server 4',
hideLabel: true,
name: 'server4'
}
],
buttons: [{
text: 'Add',
handler: function () {
settingsEmailPanel.add({
xtype: 'textfield',
fieldLabel: 'New ServerName',
name: 'newServer',
allowBlank:false
});
settingsEmailPanel.doLayout();
}
},{
text: 'Save',
handler: function () {
alert("Save clicked");
console.log(Ext.getCmp("emailForm").getForm().findField("newServer").getValue());
}
}]
});
Here what I am trying to do is onclick of save I need to query each element of form and if element xtype is textfield then getting value each by each and displaying that.
Code for save button is :
{
text: 'Save',
handler: function() {
var settingsEmailPanel = this.up().up();
var settingsEmailPanelItem = settingsEmailPanel.items.items;
for (var i = 0; i < settingsEmailPanelItem.length; i++) {
if (settingsEmailPanelItem[i].xtype == "textfield") {
var Value = settingsEmailPanelItem[i].getValue();
alert(Value)
}
}
// alert("Save clicked");
//console.log(Ext.getCmp("emailForm").getForm().findField("newServer").getValue());
}
}
I created a fiddler for you which you can check here.
Fiddle
Note : I can not see fiddle work for ExtJs 2 so I did in ExtJS 4. For making work in extJS 2 you need to assign uniqe id to each textfield and then retrive the value I suppose. The above answer will work from ExtJS 4 and above. if you make a fiddle for ExtJS 2 and I will try further more.
Just add them to an array every time you create one so you can retrieve them later in your save button handler :
var textFields = [];
/*
* [...]
*/
buttons: [{
text: 'Add',
handler: function () {
var textField = Ext.create('Ext.form.field.Text', {
xtype: 'textfield',
// ...
});
textFields.push(textFields);
settingsEmailPanel.add(textField);
settingsEmailPanel.doLayout();
}
},{
text: 'Save',
handler: function () {
for(var i=0; i<textFields.length; i++){
console.log(textFields[i].getValue());
}
}
}]

uncheck overall radiogroup radio field during load in extjs 4

Here the radio field in the radio group usually select based on the previous selection. i.e., when refresh the page it automatically set the previous value. But i need to clear the over all values from radio group.
this.mcmAdminServiceIndicatorsRadioGroup = new Ext.form.RadioGroup({
width: 350,
height: 50,
items: [
{
xtype: 'radiofield',
name: 'serviceIndicator',
fieldLabel: '',
inputValue: 'ADM',
boxLabel: 'ADM'
},
{
xtype: 'radiofield',
name: 'serviceIndicator',
margin: '0 0 0 20',
fieldLabel: '',
inputValue: 'BCK',
boxLabel: 'BCK'
},
{
xtype: 'radiofield',
name: 'serviceIndicator',
margin: '0 0 0 20',
fieldLabel: '',
inputValue: 'CKC',
boxLabel: 'CKC'
},
{
xtype: 'radiofield',
name: 'serviceIndicator',
margin: '0 0 0 20',
fieldLabel: '',
inputValue: 'BRK',
boxLabel: 'BRK'
},
{
xtype: 'radiofield',
name: 'serviceIndicator',
margin: '0 0 0 20',
fieldLabel: '',
inputValue: 'FMF',
boxLabel: 'FMF'
}
]
});
am tried these three ways inside the listner of the other radio group component..
this.mcmTaskCategoryRadiogroup = new Ext.form.RadioGroup({
width: 205,
height: 50,
items: [
{
xtype: 'radiofield',
name: 'type',
inputValue: 'Customer',
boxLabel: 'Customer',
checked: true
},
{
xtype: 'radiofield',
name: 'type',
inputValue: 'Admin',
boxLabel: 'Admin'
}
],
listeners: {
scope: this,
change: function(radiogroup, newValue, oldValue) { //will be trigger twice, one with both fields, and second with the new field
if(typeof(newValue.type) == 'string') {
if(newValue.type === 'Admin') {
this.mcmPassengerFieldSet.hide();
this.mcmPassengerServiceIndicatorsFieldSet.hide();
this.mcmAdminServiceIndicatorsFieldSet.show();
this.mcmRequestTypeCombobox.store.loadData([{ name: 'Admin' }], false);
this.mcmRequestTypeCombobox.setValue('Admin');
//this.mcmAdminServiceIndicatorsRadioGroup.setValue(false);
//this.mcmAdminServiceIndicatorsRadioGroup.setValue({ serviceIndicator: taskType });
this.mcmAdminServiceIndicatorsRadioGroup.items.items[0].setValue(true);
} else if(newValue.type === 'Customer') {
this.mcmPassengerFieldSet.show();
this.mcmPassengerServiceIndicatorsFieldSet.show();
this.mcmAdminServiceIndicatorsFieldSet.hide();
this.mcmRequestTypeCombobox.store.loadData([
{ name: '5Star' },
{ name: '5Key' },
{ name: 'Concierge Key' },
{ name: 'Focus Market' },
{ name: 'Sales' },
{ name: 'OA VIP' },
// TCS:09-24-2013 modified
{ name: 'JL VIP' },
{ name: 'BA VIP' },
{ name: 'IB VIP' },
{ name: 'QF VIP' },
// modification ended
{ name: 'Other' }
], false);
this.mcmRequestTypeCombobox.setValue(
this.mcmDisplayedRecord.get('RequestType') ? this.mcmDisplayedRecord.get('RequestType') : 'Other');
}
}
}
}
});
Have you tried removing the 'checked : true' from the Customer radiofield?
David
I think this is a bug of Ext JS. The below code is a reset function source code present in "Ext.form.field.Field" class.
reset : function(){
var me = this;
me.beforeReset();
me.setValue(me.originalValue);
me.clearInvalid();
// delete here so we reset back to the original state
delete me.wasValid;
}
Explanation:
The above function set the field value as actual original value of the field. This is working fine for all other types except "radio". The "checked:false" setting is also not working even though the base class for radio is "checkbox"(works fine for checkbox).
Problem
I think the problem is occurred after selecting any one of the options of radio/radiogroup. The radio component needs to maintain the original value properly but whenever we checked/unchecked, the original value of the radio component is changed. Thats is the reason the reset function is failed to reset the radio.
Hack
I did a hack for this problem. I am maintaing one more key for holding my original value of the radio and I manually set the value whenever I call the reset function. I have overriden the above function like this.
reset : function(){
var me = this;
me.beforeReset();
me.setValue(me.initialDefaultValue);
me.clearInvalid();
// delete here so we reset back to the original state
delete me.wasValid;
}
Now I can create a radio button something like this,
{xype: 'radio', name: 'Test', initialDefaultValue: false, boxLabel: 'Hello'}
The above solution will work fine even If you reset entire form values by calling form.reset().
Hope this help..!

Hidden fields not displaying right in formpanel

I have a formPanel with a column layout. It works perfectly as long as there are visible fields in every column.
I tried adding in hidden fields to provide space for the parts of the column where I need it but it's displaying very strangely. I did try changing to adding in textFields and hiding them but it was not keepingany space at all.
The screenshot below shows what I mean. There is a hidden field at the end of the 1st row at column 3 and at the bottom of the column 1 and 3 but the layout doesn't show that.
The hidden fields have been implemented as (with unique id/name values):
{
id:'my_field_id',
name: 'my_field_name',
xtype: 'hidden'
}
And my formpanel columns have been configured similar to:
id: 'myForm'
,title: 'Search Form'
,frame:true
,waitMessage: 'Please wait.'
,initComponent: function() {
var config = {
items: [{
layout:'table',
items:[{
//columnWidth:.25,
layout: 'form',
items: [{
xtype: 'datefield',
fieldLabel: "From Date",
id: 'date1'
},
{
xtype:'combo',
id: 'fieldSelecCmb1',
hiddenName: 'ddi_country',
anchor:'98%',
store: fieldStore,
displayField: 'name',
valueField: 'alpha2code',
selectOnFocus: true,
mode: 'local',
typeAhead: true,
editable: false,
triggerAction: 'all',
value: 'emp_id',
listeners:{
select: {
fn:function(combo, value){
myStore.load({params:{ddi_country: this.value}});
}
}
}
},
{
id:'my_field',
name: 'my_field',
xtype: 'hidden'
}
]
},
had the same problem .. we defined a component
Ext.define('NCEN.extended.columnSpacer', {
extend: 'Ext.form.field.Display',
alias: 'widget.columnSpacer',
value: ' '
});
and just use it like
xtype: 'columnSpacer'

Categories

Resources