I have created a form with two columns. In my viewcontroller I would like to access the form values.
Unfortunately I only managed to access the left column. How do I access the values of the right column
Ext.define('ocm.view.ocmMask.ModalOverviewOperationsEdit', {
extend: 'Ext.window.Window',
xtype: 'modaloperationedit',
title: 'Einsatz bearbeiten',
frame: true,
resizable: true,
width: 700,
minWidth: 700,
minHeight: 300,
bodyPadding: 0,
layout: 'column',
controller: 'overviewoperations',
defaults: {
layout: 'form',
xtype: 'container',
defaultType: 'textfield',
style: 'width: 50%'
},
items: [{
//I get the Values of this column
xtype: 'form',
items: [
{
xtype: 'datefield',
fieldLabel: BpcCommon.lang.Current.OCM_MASK_DATE,
maxValue: new Date(),
bind: "{operation.ALARMIERUNGSDATUM}",
name: 'ALARMIERUNGSDATUM',
required: true
}]
}, {
//I didn't get this values
items: [
{
xtype: 'combobox',
store: "ocmKeywordStore",
valueField:'ID',
name: "ALLOCATION",
id: "ALLOCATION",
fieldLabel: BpcCommon.lang.Current.OCM_MASK_ALLOCATION,
displayField:'Text',
queryParam: false,
editable: false,
}]
}],
In the view controller I access it as follows
Ext.define('ocm.view.ocmMask.OverviewOperationsController', {
extend: 'Ext.app.ViewController',
alias: 'controller.overviewoperations',
updateOperation: function(btn){
var win = btn.up('window'),
getForm = win.down('form');
var values = getForm.getValues();
console.log(values);
}
});
The main problem is that your second field is not inside your form.
Right now you have an Ext.window.Window with the layout column that contains a form with a datefield and a container that contains a Combobox.
So your getValues(https://docs.sencha.com/extjs/6.0.1/classic/Ext.form.Panel.html#method-getValues) method does the right thing and gives you all values from fields that are contained or inside your form.
I just did a small fiddle. Maybe you more looking for an approach like this?
https://fiddle.sencha.com/#view/editor&fiddle/36kq
Related
I have a form within a form. I need to bind the hidden property of a field in the outer form to the checked state of a field in the inner form. I assume I can do this with binding by setting up a custom getter/setter but not exactly sure... here's the idea:
Sencha fiddle
You can do something like this:
Ext.define('Test.InnerForm', {
extend: 'Ext.form.Panel',
xtype: 'innerform',
defaultListenerScope: true,
config: {
isFoo: false
},
twoWayBindable: {
isFoo: true
},
publishes: ['isFoo'],
items:[{
xtype: 'checkbox',
fieldLabel:'cb',
listeners: {
change: 'onCheckChange'
}
}],
onCheckChange: function(box, checked) {
this.setIsFoo(checked);
}
});
Ext.define('Test.OuterForm', {
extend: 'Ext.form.Panel',
xtype: 'outerform',
viewModel: true,
items:[{
xtype:'innerform',
reference: 'innerform'
},{
xtype: 'textfield',
fieldLabel: 'want to hide this when cb is checked',
bind: {
hidden: '{innerform.isFoo}'
}
}]
});
Ext.create('Test.OuterForm', {
title: 'Outer form',
width: 500,
height: 500,
bodyPadding: 10,
renderTo: Ext.getBody()
});
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'
}]
});
so I have a view where I display a combobox and a grid that share a 'Roles' store. If you pick an option on the combobox, the grid will be filtered accordingly.
I am looking for a way to add an "All" option to the combobox that is selectable (so placeholder or value attributes don't work for me). I want to do this because I cannot add that option to the store without affecting the grid as well.
This is my code:
Ext.define("MODIFE.view.administration.Roles",{
extend: "Ext.panel.Panel",
xtype: "app-administration-roles",
controller: "administration-roles",
viewModel: {
type: "administration-users"
},
title: "Roles",
items:[
{
title: 'Búsqueda de Roles',
frame: true,
resizable: true,
xtype: 'form',
layout: 'column',
defaults: {
layout: 'form',
xtype: 'container',
defaultType: 'textfield',
style: 'width: 50%'
},
items: [{
items: [{
fieldLabel: 'Rol',
xtype: 'combobox',
store: 'Roles',
displayField: 'Description',
valueField: 'RoleId',
}]
}, {
items: [
{ fieldLabel: 'Estatus', xtype: 'combobox' },
]
}],
buttons: [
{ text: 'Nuevo' },
{ text: 'Buscar' }
]
},
{
layout: 'fit',
items: [{
xtype: 'grid',
id: 'rolesGrid',
title: 'Listado de Roles',
store: 'Roles',
columns: [
{ text: 'Rol', dataIndex: 'Description', flex: 2},
{ text: 'Estatus', dataIndex: 'Status', flex: 2},
]
}]
}]
});
Thanks in advance!
You could clone the store, then any alterations wont be reflected in the original store. (but it's messy, and may have problems with syncing if you have this enabled)
//clone store
var records = [],
me = this;
me.store.each(function(r){
records.push(r.copy());
});
var store2 = new Ext.data.Store({
recordType: me.store.recordType,
model: me.store.model
});
store2.add(records);
//add record
store2.add({ID:"-1", NAME: "-Please select-"});
I'm having an issue with multiple instances of an ext js grid all showing the same data. I am using Ext js 4.1.1.
I have a main tab panel. In that panel, there are multiple people tabs. Inside each person tab is a details tab and a family tab.
The details tab is a simple form with text boxes, combo boxes, etc. The family tab has both a dataview and a grid.
If only one person tab is open at a time, everything works fine. As soon as a second person is opened, the family tabs look the same (both the dataview and the grid). It seems to me that the problem has something to do with the model. Perhaps they are sharing the same instance of the model, and that is causing one refresh to change all the data. The dataview and the grid both have the same problem, but I think that if I can fix the problem with the grid, then I can apply the same logic to fix the dataview. I will leave the code for the dataview out of this question unless it becomes relevant.
PersonTab.js
Ext.require('Client.view.MainTab.PersonDetailsForm');
Ext.require('Client.view.MainTab.PersonFamilyForm');
Ext.require('Client.view.MainTab.EventForm');
Ext.define('Client.view.MainTab.PersonTab',
{
extend: 'Ext.tab.Panel',
waitMsgTarget: true,
alias: 'widget.MainTabPersonTab',
layout: 'fit',
activeTab: 0,
tabPosition: 'bottom',
items:
[
{
title: 'Details',
closable: false,
xtype: 'MainTabPersonDetailsForm'
},
{
title: 'Family',
closable: false,
xtype: 'MainTabPersonFamilyForm'
},
{
title: 'page 3',
closable: false,
xtype: 'MainTabEventForm'
}
]
});
MainTabPersonFamilyForm.js
Ext.require('Client.view.MainTab.PersonFamilyHeadOfHouseholdDataView');
Ext.require('Client.view.MainTab.PersonFamilyGrid');
Ext.define('Client.view.MainTab.PersonFamilyForm',
{
extend: 'Ext.form.Panel',
alias: 'widget.MainTabPersonFamilyForm',
waitMsgTarget: true,
padding: '5 0 0 0',
autoScroll: true,
items:
[
{
xtype: 'displayfield',
name: 'HeadOfHouseholdLabel',
value: 'The head of my household is:'
},
{
xtype: 'MainTabPersonFamilyHeadOfHouseholdDataView'
},
{
xtype: 'checkboxfield',
boxLabel: "Use my Head of Household's address as my address",
boxLabelAlign: 'after',
inputValue: true,
name: 'UseHeadOfHouseholdAddress',
allowBlank: true,
padding: '0 20 5 0'
},
{
xtype: 'MainTabPersonFamilyGrid'
}
],
config:
{
idPerson: ''
}
});
MainTabPersonFamilyGrid.js
Ext.require('Client.store.PersonFamilyGrid');
Ext.require('Ext.ux.CheckColumn');
Ext.define('Client.view.MainTab.PersonFamilyGrid',
{
extend: 'Ext.grid.Panel',
alias: 'widget.MainTabPersonFamilyGrid',
waitMsgTarget: true,
padding: '5 0 0 0',
xtype: 'grid',
title: 'My Family Members',
store: Ext.create('Client.store.PersonFamilyGrid'),
plugins: Ext.create('Ext.grid.plugin.CellEditing'),
viewConfig:
{
plugins:
{
ptype: 'gridviewdragdrop',
dragGroup: 'PersonFamilyGridTrash'
}
},
columns:
[
{ text: 'Name', dataIndex: 'Name'},
{ text: 'Relationship', dataIndex: 'Relationship', editor: { xtype: 'combobox', allowblank: true, displayField: 'display', valueField: 'value', editable: false, store: Ext.create('Client.store.Gender') }},
{ xtype: 'checkcolumn', text: 'Is My Guardian', dataIndex: 'IsMyGuardian', editor: { xtype: 'checkboxfield', allowBlank: true, inputValue: true }},
{ xtype: 'checkcolumn', text: 'I Am Guardian', dataIndex: 'IAmGuardian', editor: { xtype: 'checkboxfield', allowBlank: true, inputValue: true } }
],
height: 200,
width: 400,
buttons:
[
{
xtype: 'button',
cls: 'trash-btn',
iconCls: 'trash-icon-large',
width: 64,
height: 64,
action: 'trash'
}
]
});
PersonFamilyGrid.js (store)
Ext.require('Client.model.PersonFamilyGrid');
Ext.define('Client.store.PersonFamilyGrid',
{
extend: 'Ext.data.Store',
autoLoad: false,
model: 'Client.model.PersonFamilyGrid',
proxy:
{
type: 'ajax',
url: '/Person/GetFamily',
reader:
{
type: 'json'
}
}
});
PersonFamilyGrid.js (model)
Ext.define('Client.model.PersonFamilyGrid',
{
extend: 'Ext.data.Model',
fields:
[
'idFamily',
'idPerson',
'idFamilyMember',
'Name',
'Relationship',
'IsMyGuardian',
'IAmGuardian'
]
});
relevant code from the controller:
....
....
var personTab = thisController.getMainTabPanel().add({
xtype: 'MainTabPersonTab',
title: dropData.data['Title'],
closable: true,
layout: 'fit',
tabpanelid: dropData.data['ID'],
tabpaneltype: dropData.data['Type']
});
personTab.items.items[0].idPerson = dropData.data['ID'];
personTab.items.items[1].idPerson = dropData.data['ID'];
thisController.getMainTabPanel().setActiveTab(personTab);
....
....
You're setting the store as a property on your grid prototype and creating it once at class definition time. That means that all your grids instantiated from that class will share the exact same store.
Note that you're also creating a single cellediting plugin that will be shared with all instantiations of that grid as well. That definitely won't work. You likely will only be able to edit in either the first or last grid that was instantiated.
In general you should not be setting properties like store, plugins, viewConfig or columns on the class prototype. Instead you should override initComponent and set them inside that method so that each instantiation of your grid gets a unique copy of those properties.
Ext.define('Client.view.MainTab.PersonFamilyGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.MainTabPersonFamilyGrid',
waitMsgTarget: true,
padding: '5 0 0 0',
title: 'My Family Members',
height: 200,
width: 400
initComponent: function() {
Ext.apply(this, {
// Each grid will create its own store now when it is initialized.
store: Ext.create('Client.store.PersonFamilyGrid'),
// you may need to add the plugin in the config for this
// grid
plugins: Ext.create('Ext.grid.plugin.CellEditing'),
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop',
dragGroup: 'PersonFamilyGridTrash'
}
},
columns: /* ... */
});
this.callParent(arguments);
}
});
It's hard to tell exactly, but from the code you have submitted it appears that you are not setting the id parameter on your tabs and your stores, which causes DOM collisions as the id is used to make a component globally unique. This has caused me grief in the past when sub-classing components (such as tabs and stores) and using multiple instances of those classes.
Try giving each one a unique identifier (such as the person id) and then referencing them using that id:
var personTab = thisController.getMainTabPanel().add({
id: 'cmp-person-id',
xtype: 'MainTabPersonTab',
...
store: Ext.create('Client.store.PersonFamilyGrid',
{
id: 'store-person-id',
...
});
Ext.getCmp('cmp-person-id');
Ext.StoreManager.lookup('store-person-id');
Hope that helps.
I have a form with dynamically added fields (varying sizes).
I would like to put a number of form fields in a fieldset, and have the fieldset border just large enough to contain all the fields.
Here is an (ugly) example that shows the issue:
var win = new Ext.Window({
xtype: 'form',
layout: 'form',
height: 200,
width: 500,
title: 'Testing',
items: [{
xtype: 'fieldset',
layout: 'hbox',
autoHeight:true,
autoWidth: false,
title: 'Fieldset',
defaults: {
border: false,
layout: 'form',
labelAlign: 'top',
labelSeparator: ''
},
items: [{
items: new Ext.form.TextField({
fieldLabel: 'Col1',
name: 'col1',
value: 'nothing',
})
}, {
items: new Ext.form.TextField({
fieldLabel: 'Col2',
name: 'col2',
value: 'something'
})
}]
},
new Ext.form.TextField({
fieldLabel: 'Col3',
name: 'col3',
value: 'anything'
})
]
}).show();
This is what it looks like:
I will not know the width of the contained fields beforehand, so I can't specify a width.
Thanks for any suggestions.
Not what you asked for, but adding flex: 1 to the defaults for the fieldset makes the fields arrange themselves evenly within the bounds of the fieldset.
Ok, works by changing some fieldset properties:
layout to 'table',
autoWidth to true,
adding a cls with 'float:left', (putting this in style doesn't seem to help)
and adding a dummy element to clear the float:
{
xtype: 'component',
style: 'clear:both'
}
It now shows as desired!