I intend to change the state of several fields in a form (hide) according to the value selected in a combobox.
This can be done using methods such as setVisible () or setHidden ().
It will be possible to achieve this goal using binding component state?
SOLVED
Fiddle https://fiddle.sencha.com/#fiddle/1itf
Yes. Using ViewModel formulas. Quoting from the documentation:
Many configs you will want to bind are boolean values, such as visible (or hidden), disabled, checked, and pressed. Bind templates support boolean negation "inline" in the template. Other forms of algebra are relegated to formulas (see below), but boolean inversion is common enough there is special provision for it.
Basically, you can using bindings to control the visible attribute, but the binding needs to be a boolean value. You can see that with your 'isAdmin' check. So what you need to do is create a formula on the ViewModel and bind to that.
Ext.define('My.ViewModel', {
extend: 'Ext.app.ViewModel',
formulas: {
isAlabama: function(get) {
return get('comboboxvalue') === 'AL';
}
}
}
To use this, you'll need to say that you're using this view model in your panel. Also... you see the comboboxvalue bit? Well, it looks like ComboBoxes don't publish their value attribute to the view model automatically - you need to do that explicitly, like so:
{ xtype: 'combobox',
fieldLabel: 'Choose State',
store: states,
queryMode: 'local',
displayField: 'name',
valueField: 'abbr',
reference:'combobox',
bind: {
value: '{comboboxvalue}'
}
}
There may be a more elegant solution but you could add an attribute into your store to determine to hide or not, then bind to that attribute:
Ext.application({
name : 'Fiddle',
launch : function() {
}
});
var states = Ext.create('Ext.data.Store', {
fields: ['abbr', 'name'],
data : [
{"abbr":"AL", "name":"Alabama", "hide": 0},
{"abbr":"AK", "name":"Alaska", "hide": 1},
{"abbr":"AZ", "name":"Arizona", "hide": 1}
]
});
Ext.create('Ext.form.Panel', {
title: 'Sign Up Form',
width: 300,
height: 230,
bodyPadding: 10,
margin: 10,
layout: {
type:'anchor',
align: 'stretch'
},
viewModel: true,
items: [{
xtype: 'checkbox',
boxLabel: 'Is Admin',
reference: 'isAdmin'
},{
xtype: 'textfield',
fieldLabel: 'Admin Key',
bind: {
visible: '{!isAdmin.checked}'
}
},{
xtype : 'menuseparator',
width : '100%'
},{
xtype: 'combobox',
fieldLabel: 'Choose State',
store: states,
queryMode: 'local',
displayField: 'name',
valueField: 'abbr',
reference:'combobox'
},{
xtype: 'textfield',
fieldLabel: 'If Alabama, hide',
bind: {
visible: '{combobox.selection.hide}'
}
},{
xtype: 'textfield',
fieldLabel: 'If Alaska, hide',
bind: {
visible: '{}'
}
},{
xtype: 'textfield',
fieldLabel: 'If Arizona, hide',
bind: {
visible: '{}'
}
}],
renderTo: Ext.getBody()
});
Related
I want to binding a field state (disabled or hidden) according to different selected values in a combobox.
If just one option is selected in combobox works great
Fiddle: https://fiddle.sencha.com/#fiddle/1itf
stackoverflow: Binding component state conditionally
I tried the following way:
bind: {
disabled: ('{isAlabama} || {isAlaska}')
},
Apparently it works. If I select Alabama or Alaska, the field Alabama is hidden.
The problem is that when I select the combobox value Arizona should display the fields
Alabama and Alaska, which does not, just show Alaska.
Fiddle: https://fiddle.sencha.com/#fiddle/1j36 EDITED
It is possible to do this with binding?
I reworded the formulas slightly and moved the AL||AK logic into the hideAlabama formula instead of it being in the disabled property. This keeps the hidden property to a single formula evaluation, as it seemed that multiple formula evaluations were not behaving as expected.
Ext.application({
name : 'Fiddle',
launch : function() {
}
});
var states = Ext.create('Ext.data.Store', {
fields: ['abbr', 'name'],
data : [
{"abbr":"AL", "name":"Alabama"},
{"abbr":"AK", "name":"Alaska"},
{"abbr":"AZ", "name":"Arizona"}
]
});
Ext.define('My.ViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myviewmodel',
formulas: {
hideAlabama: function(get) {
return get('comboboxvalue') === 'AL' || get('comboboxvalue') === 'AK';
},
hideAlaska: function(get) {
return get('comboboxvalue') === 'AK';
},
hideArizona: function(get) {
return get('comboboxvalue') === 'AZ';
}
}
});
Ext.create('Ext.form.Panel', {
title: 'Sign Up Form',
width: 300,
height: 230,
bodyPadding: 10,
margin: 10,
layout: {
type:'anchor',
align: 'stretch'
},
viewModel:{
type: 'myviewmodel'
},
items: [{
xtype: 'combobox',
fieldLabel: 'Choose State',
store: states,
queryMode: 'local',
displayField: 'name',
valueField: 'abbr',
reference:'combobox',
bind: {
value: '{comboboxvalue}'
}
},{
xtype: 'textfield',
fieldLabel: 'If Alabama, hide',
bind: {
hidden: '{hideAlabama}'
}
},{
xtype: 'textfield',
fieldLabel: 'If Alaska, hide',
bind: {
hidden: '{hideAlaska}'
}
},{
xtype: 'textfield',
fieldLabel: 'If Arizona, hide',
bind: {
hidden: '{hideArizona}'
}
}],
renderTo: Ext.getBody()
});
I defined a view that should be able to be called in two modes. There are only two differences depending on a flag:
title of view (config.title)
selectfield might be shown or hidden
Here is the simplified view:
Ext.define('MyApp.view.fancyView', {
xtype: 'fancyview',
extend: 'Ext.form.Panel',
config: {
cls: 'fancyviewclass',
title: "titleDependingOnFlag",
items: [
{
xtype: 'fieldset',
name: 'fieldsetFancy',
items: [
{
xtype: 'selectfield',
itemId: 'stateID',
usePicker: true,
label: 'state',
store: 'States',
name: 'StateID',
valueField: 'ID',
displayField: 'ID'
},
{
xtype: 'selectfield',
itemId: 'countryID',
usePicker: true,
label: 'country',
store: 'Countries',
name: 'CountryID',
valueField: 'ID',
displayField: 'ID',
//hidden: true
}
]
}
]
}
});
And of course there is a controller that creates this view. At the moment I'm passing the flag as config value, see
Ext.define('MyApp.controller.fancyController', {
...
raisedBasedOnTap:function (flag){
this.myFancyFlag = !!flag;
var myFancyView = Ext.create('FLSMOBILE.minimax.view.CallReportTimestampPlaceCar', {
myFancyFlag: me.myFancyFlag
});
app.pushView(myFancyView);
}
...
});
What would be the best approach to make the title depending on a flag (like title: fancyFlag? 'title1' : 'title2') and hide selectfield countryID based on the flag?
Thanks in advance!
I have a code in which I created a component. On click of apply I want to save this forms fields object and make available for getter. So that Parent container can read that.
I also want all field getter/setter, so that can update value runtime. How to achieve this?
Ext.define('MyApp.view.MyForm', {
extend: 'Ext.form.Panel',
height: 463,
width: 227,
bodyPadding: 10,
title: 'My Form',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [
{
xtype: 'textfield',
fieldLabel: 'Component Name',
anchor: '100%'
},
{
xtype: 'textfield',
fieldLabel: 'Host',
anchor: '100%'
},
{
xtype: 'textfield',
fieldLabel: 'Port',
anchor: '100%'
},
{
xtype: 'textfield',
fieldLabel: 'Path',
anchor: '100%'
},
{
xtype: 'textareafield',
fieldLabel: 'Request Data',
anchor: '100%'
},
{
xtype: 'button',
text: 'Apply',
listeners: {
click: {
fn: me.onButtonClick,
scope: me
}
}
}
]
});
me.callParent(arguments);
},
onButtonClick: function(button, e, options) {
var form = this.getForm(),
values = form.getFieldValues(),
//make this available to public
json = Ext.JSON.encode(values);
console.log(json);
}
});
In order to achieve this need to define all variables inside config:{} extjs will automatically create getter/setter.
You can then reference it using this.getVar(), this.setVar()
I hope this is helpful for beginners.
Refer configuration section at http://docs.sencha.com/ext-js/4-0/#!/guide/class_system for more details
Good day everybody,
I have a recurrent problem when I work with ExtJS 4.1: I do a lot of effort every time I have to establish a reference to an object and often, when I call up a method on an object, I get an error like this:
Uncaught TypeError: Cannot call method 'destroy' of undefined
For instance, consider the following situation where I have a fieldset which contains two items: a fieldcontainer and a button.
My purpose is writing a proper handler function for the button, so that when I hit the button the fieldcontainer will be destroyed. To do that, I need to establish a correct reference to the fieldcontainer.
Here's my code:
xtype: 'fieldset',
id: 'product_fieldset',
title: 'Prodotti tempi e quantita',
defaultType: 'textfield',
layout: 'anchor',
items: [{
xtype: 'fieldcontainer',
layout: 'hbox',
defaultType: 'textfield',
defaults: {
labelAlign: 'top'
},
items: [{
xtype: 'combo',
name: 'product',
fieldLabel: 'Product',
forceSelection: true,
editable: false,
store: products,
queryMode: 'local',
displayField: 'name',
valueField: 'name',
allowBlank: false,
afterLabelTextTpl: required
},{
xtype: 'numberfield',
name: 'p_on_weight',
fieldLabel: '% on weight',
value: 0,
minValue: 0,
allowBlank: false,
afterLabelTextTpl: required,
hideTrigger: true,
keyNavEnabled: false,
mouseWheelEnabled: false
},{
xtype: 'numberfield',
name: 'time',
fieldLabel: 'Time (minutes)',
value: 0,
minValue: 0,
allowBlank: false,
afterLabelTextTpl: required,
hideTrigger: true,
keyNavEnabled: false,
mouseWheelEnabled: false
},{
xtype: 'numberfield',
name: 'ph',
fieldLabel: 'Ph',
minValue: 0,
allowBlank: false,
afterLabelTextTpl: required,
hideTrigger: true,
keyNavEnabled: false,
mouseWheelEnabled: false
},{
xtype: 'textareafield',
name: 'remarks',
fieldLabel: 'Remarks'
}]
},{
xtype: 'button',
text: 'Delete this product',
handler: function() {
proper_reference_to_fieldcontainer.destroy();
//need help for previous line
}
}]
Well, Can anyone suggest me a way to refer to fieldcontainer, possibly without using fieldcontainer's id ? (Sencha architects suggest not to use id to establish references).
Thanks in advance.
Enrico.
You can define the container as a standalone object:
var myFieldContainer = Ext.Create('Ext.form.FieldContainer', {
layout: 'hbox',
defaultType: 'textfield',
defaults: {
labelAlign: 'top'
},
items: [{
xtype: 'combo',
(...)
});
...and then use it in your button's configuration:
{
xtype: 'button',
text: 'Delete this product',
handler: function () {
myFieldContainer.destroy();
}
}
Use first define an id value for fieldcontainer,
xtype: 'fieldcontainer',
id: 'my_id',
layout: 'hbox',
Now use Ext.getCmp('my_id') to retrieve a reference to it.
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'