ExtJS 4 RadioGroup Change Event Fires Twice - extjs

I'm using ExtJS 4.0.7, am new to Ext, and am using the new MVC architecture. I have a RadioGroup that, upon change, I want to use to reveal more UI elements. The problem is, that the change event fires twice for the RadioGroup. I'm assuming this is because both Radios fire an event for having their values change.
Is there a way to listen for a change to either the RadioGroup or Radios with the same name that will fire only once? In my experience with jQuery and Flex, I would expect a RadioGroup to only fire once.
Here's the RadioGroup code in my view:
items: [{
xtype: 'radiogroup',
id: 'WheatChoice',
padding: '',
layout: {
padding: '-3 0 4 0',
type: 'hbox'
},
fieldLabel: 'Choose Model',
labelPad: 5,
labelWidth: 80,
allowBlank: false,
columns: 1,
flex: 1,
anchor: '60%',
items: [
{ xtype: 'radiofield', id: 'SpringWheat', padding: '2 10 0 0', fieldLabel: '',
boxLabel: 'Spring', name: 'wheat-selection', inputValue: '0', flex: 1 },
{ xtype: 'radiofield', id: 'WinterWheat', padding: '2 0 0 0', fieldLabel: '',
boxLabel: 'Winter', name: 'wheat-selection', inputValue: '1', checked: true, flex: 1 }
]
}]
Here's the relevant code in my Controller:
init: function() {
this.control({
'#WheatChoice': {
change: this.onWheatChange
}
});
},
onWheatChange: function(field, newVal, oldVal) {
//this fires twice
console.log('wheat change');
}

http://www.sencha.com/forum/showthread.php?132176-radiogroup-change-event-fired-twice/page2
evant says this will be fixed with 4.1, so it's definitely a bug.
However, you can deal with the situation pretty easily:
//borrowing your function
onWheatChange: function(rg, sel) {
var selection = sel['wheat-selection'];
if (!(selection instanceof Object)) {
alert(selection);
}
}
var selection will be the new value. I know it doesn't solve the two event firing problem, but hopefully this helps!

The reason it fires twice is because your radio group has two changes happening.
A radio button is changing from checked=true to checked=false and then your newly clicked radio button is changing from checked=false to checked=true. This should really be an expected thing.
What if you wanted to do something when a radio button was no longer checked? You'd miss that entire event. Really you should just be doing a check on your listener function to only listen for the radio button that has checked=true.

It might be getting fired because the initial value is being set and that triggers the event. Try adding a third radio element and see if it fires three times.

Try this:
change : function(thisFormField, newValue, oldValue, eOpts) {
if (!Ext.isArray(newValue.myTransitionsRadio)) {
// Code goes here.
}
Here myTransitionsRadio in my case, is the common name given to all radio buttons.
Thanks
Nagendra

Related

extjs radiogroup before change event

Could you please help me before change/check the event on ExtJS radiogroup. I want some event should check before changing the radio button based on the condition. I need to allow user to change the select another radio button if condition says false, then we need to select the old radio button only.
Please refer the below code:
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create('Ext.form.Panel', {
title: 'RadioGroup Example',
width: 300,
height: 125,
bodyPadding: 10,
renderTo: Ext.getBody(),
items: [{
xtype: 'radiogroup',
fieldLabel: 'Gender',
columns: 1,
items: [{
boxLabel: 'Male',
name: 'rb',
inputValue: '1'
}, {
boxLabel: 'Female',
name: 'rb',
inputValue: '2',
}],
listeners: {
change: function(field, newValue, oldValue, eOpts) {
console.log(newValue);
alert(newValue.rb);
},
}
}]
});
}
});
https://fiddle.sencha.com/#view/editor&fiddle/32fb
As mentioned in the comments, there is no beforechange event that can be used to veto a change.
Some other options are:
you can the change listener to validate the radiogroup, making it invalid if an option is selected that's not right. This way the user is passively informed that there's a problem, and they have to fix it.
you can get the behaviour you described by using the oldvalue argument, and simply setting the radio control back to the old value:
change: function(field, newValue, oldValue, eOpts) {
if (<new value isn't acceptable>) {
// Probably should let the user know why
field.setValue(oldValue);
return;
}
... any other change logic here.
}
You can also use the change listener enable and disable options pre-emptively as the form state changes, thus preventing the user from making a bad choice in the first place.

How to Set Single Field Dirty in ExtJS

PROBLEM: We toggle fields on form. When secondField is shown instead of firstField, then form is changed. But secondField is still marked as not dirty, because both fields remain unchanged. Showing secondField should always make it and the form (model) dirty.
RESEARCH: setDirty() method is done on whole record, setValue() acts as expected, but smells like a hack and can't be used for various field types (textfield, combobox).
QUESTION: How to manually set a single form field state changed to invoke saving its data?
You are mixing up data state with form visualisation. By default, "field is shown" has no relation to data, so you need to explicitly create one. This can be done by changing some data on toggling, or other way round — toggling on changing data.
For example, toggling can occur on checking/unchecking a checkbox field which will represent a piece of form data (also see fiddle):
Ext.create('Ext.form.Panel', {
viewModel: {
type: 'default'
},
items: [
{
xtype: 'checkbox',
reference: 'toggle',
itemId: 'toggle',
boxLabel: 'Toggle',
hidden: true
},
{
xtype: 'button',
text: 'Toggle',
enableToggle: true,
toggleHandler: function() {
var form = this.up('form'),
checkbox = form.child('#toggle');
checkbox.setValue(!checkbox.getValue());
console.log(form.isDirty() ? 'Dirty!' : 'Not dirty');
}
},
{
xtype: 'textfield',
name: 'firstField',
fieldLabel: 'First Field',
bind: {
hidden: '{toggle.checked}'
}
},
{
xtype: 'textfield',
name: 'secondField',
fieldLabel: 'Second Field',
bind: {
hidden: '{!toggle.checked}'
}
}
],
renderTo: Ext.getBody()
});

How can you dynamically change the disabled property of a Sencha text field?

I have a formPanel set up with a text field. When a button is pressed, I would like it to change the disabled property of the text field from true to false, allowing it to be editable. The problem is that I don't know how to make this stick. Here's the form code:
myApp.views.formContainer = new Ext.form.FormPanel({
id: 'inspectionForm',
layout: 'vbox',
width: '100%',
items: [{
xtype: 'textfield',
name: 'myText',
id: 'myText',
label: 'License Plate',
width: '90%'
},
{
xtype: 'button',
text: 'Submit',
height: 40,
ui: 'confirm-round',
handler: function()
{
Ext.get('myText').disabled = false;
}
}]
});
The thing about Ext.get('mytext'),disabled = false; is that it works. Checking it later shows that the disabled attribute is set to false. But you still can't edit it. Does anyone know how to do this?
By calling Ext.getCmp('mytext').disabled = false; you only change the initial config property. To actually modify the component use Ext.getCmp('mytext').enable(); and Ext.getCmp('mytext').disable();

How to refer to a tabpanels tab, from inside

I have a tabpanel which is part of a form (input fields are on different tabs). I need to inform the user on submission if a form has invalid fields even if they are not on the current tab. I think the best way would be to change the tabs color.
The question is how can I get the reference for the tab button, without introducing a new id?
Here is what i was trying to do, turned out to be a dead end since i get reference to the tab inner body, and with one more up to the entire tab panel
...
xtype:'tabpanel',
plain:true,
activeTab: 0,
height:190,
margin: '10 0 0 0',
items: [{
title: 'Personal',
layout:'column',
border:false,
items:[{
columnWidth:.5,
border:false,
layout: 'anchor',
defaultType: 'textfield',
items: [{
fieldLabel: 'Email',
name: 'user[email]',
allowBlank: false,
listeners: {
'validitychange': function(th, isvalid, eOpts) {
if(!isvalid) {
alert(this.up().up().getId());
};
}
},
vtype:'email',
anchor:'95%'
}]
}]
}]
Try this:
From your field or any other Component in the panel (like a button) :
this.up('tabpanel').down('tab').el.applyStyles('background:red')
if the tab in question is not the first tab, you can use any tab property in the selector like this: ...down('tab[text=Example]') . You can use id property if you have it, if not you can just make up any property and set it to something meaningful like "ref:FirstTab".
If you have access to the tabPanel then you can access the items of its tabBar directly with:
this.up('tabpanel').getTabBar().items.get(0)
this.up('tabpanel').getTabBar().items.get(1)
etc.
See http://docs.sencha.com/extjs/4.1.3/#!/api/Ext.tab.Bar-property-items

Extjs radiogroup with buttons

For making a toolbox, I want to know how to make a radiogroup with regular buttons and not radiobuttons in latest extJS
Like this with jQueryUI: http://jqueryui.com/demos/button/#radio
Thanks in advance,
Chielus
I think you should look at using a set standard ExtJS buttons. A button can be assigned to a group so that they act as the elements shown in your link.
See this example:
{
xtype: 'button',
text: 'Choice 1',
toggleGroup: 'mygroup'
}, {
xtype: 'button',
text: 'Choice 2',
toggleGroup: 'mygroup'
}, {
xtype: 'button',
text: 'Choice 3',
toggleGroup: 'mygroup'
}
Buttons also have a property called enableToggle, that allows them to toggle, and is automatically set to true when you set a toggleGroup, and toggleGroup tells ExtJS how they are related.
Note, they look like regular ExtJS buttons, but behave like you want.
There is a less complicated (better?) way to disallow deselecting a button. Set the allowDepress config option to false:
{
xtype: 'radiogroup',
layout: 'hbox',
defaultType: 'button',
defaults: {
enableToggle: true,
toggleGroup: 'mygroup',
allowDepress: false,
items: [
{ text: 'Choice 1'},
{ text: 'Choice 2'},
{ text: 'Choice 3'}
]
}
}
Just to answer #mastak's comment (in the answer above), in order to disallow the action of de-selecting a button, add this listener to each button:
listeners: {
click: function(me, event) {
// make sure a button cannot be de-selected
me.toggle(true);
}
}
That way, each click on a button will re-select it.
-DBG
Just adding to the #deebugger post. You can also use the following button property to not allow to deselect a selection
Ext.create('Ext.Button', {
renderTo : Ext.getBody(),
text : 'Click Me',
enableToggle : true,
allowDepress : false
});

Resources