I am trying to find the best way to bind items to a textfield in my extjs project. I downloaded the data into a store with one record in the controller. How would I bind to this textfield from the one record? I would preferably bind in the view, not in the controller
You should read this guide to understand better what binding is
The best solution for you is bind the record on the viewmodel of the view, so:
textfield.setBind({
value:'{myRec.valueToRefer}'
})
viewmodel.set('myRec',record.getData());
If you want, you can also use a form to handle this, using form.loadRecord and giving to the textfield a name..
A tip:
set inside the viewmodel a value to null:
data:{
myRec:null
}
Set your record in the viewmodel after setting the bind to the textfield.
Other tip:
If you can, avoid using setBind and prefer to set the binding directly on textfield creation:
//WILL WORK BUT YOU CAN AVOID IT
textfield.setBind({
value:'{myRec.valueToBind}'
})
//YES
var textfield=Ext.create({
xtype:'textfield',
bind:{
value:'{myRec.valueToBind}'
}
});
Refer to Sencha documentation also
You can use bind config to bind the data or any other config for ExtJS component.
Bind setting this config option adds or removes data bindings for other configs.
For example, to bind the title config:
var panel = Ext.create({
xtype: 'panel',
bind: {
title: 'Hello {user.name}'
}
});
To dynamically add bindings:
panel.setBind({
title: 'Greetings {user.name}!'
});
To remove bindings:
panel.setBind({
title: null
});
In this FIDDLE, I have created a demo for biding. I hope this will help/guide you to achieve you requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
//defining Store
Ext.define('Store', {
extend: 'Ext.data.Store',
alias: 'store.gridstore',
autoLoad: true,
fields: ['name', 'email', 'phone'],
proxy: {
type: 'ajax',
url: 'data1.json',
reader: {
type: 'json',
rootProperty: ''
}
}
});
//defining view model
Ext.define('MyViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myvm',
data: {
formdata: null
},
stores: {
gridstore: {
type: 'gridstore'
}
}
});
//Controller
Ext.define('MyViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.myview',
onGridItemClick: function (grid, record) {
//Bind the form data for CLICKED record
this.getViewModel().set('formdata', record)
}
});
//creating panel with GRID and FORM
Ext.create({
xtype: 'panel',
controller: 'myview',
title: 'Binding Example',
renderTo: Ext.getBody(),
viewModel: {
type: 'myvm'
},
layout: 'vbox',
items: [{
xtype: 'grid',
flex: 1,
width: '100%',
bind: '{gridstore}',
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone'
}],
listeners: {
itemclick: 'onGridItemClick'
}
}, {
xtype: 'form',
flex: 1,
width: '100%',
defaults: {
anchor: '100%'
},
title: 'Bind this form on Grid item Click',
bodyPadding:15,
margin: '20 0 0 0',
// The fields
defaultType: 'textfield',
items: [{
fieldLabel: 'Name',
name: 'first',
allowBlank: false,
bind: '{formdata.name}'
}, {
fieldLabel: 'Email',
name: 'email',
allowBlank: false,
bind: '{formdata.email}'
}, {
fieldLabel: 'Phone',
name: 'phone',
allowBlank: false,
bind: '{formdata.phone}'
}]
}]
});
}
});
Related
See this fiddle: https://fiddle.sencha.com/#view/editor&fiddle/36vh.
Even though the defaultFocus is set properly by referencing the component via #fldxyz, the component doesn't get the focus.
Ext.application({
name : 'myapp',
// autoCreateViewport is deprecated
mainView: 'myapp.MyPanel',
launch : function() {
}
});
Ext.define('myapp.MyPanel', {
extend: 'Ext.panel.Panel', // does not work
// extend: 'MyPanel', // works
layout: 'fit',
//defaultFocus: '[reference=fld]',
//defaultFocus: 'textfield:first',
defaultFocus: '#fldxyz',
items: [{
xtype: 'form',
layout: 'anchor',
items: [{
xtype: 'textfield',
fieldLabel: 'Name',
value: 'Indigo',
id: 'fldxyz',
//reference: 'fld',
selectOnFocus: true
}, {
xtype: 'textfield',
fieldLabel: 'Last',
value: 'Montoya'
}]
}]
});
I tested it with 6.6.0 and 7.2.0.
What's wrong?
Thanks
In the doc of defaultFocus is following: Specifies a child Component to receive focus when this Container's method-focus method is called.
You are not calling the focus() method and it is not focused. I have added it in the 'afterrender' listener event.
Ext.application({
name : 'myapp',
mainView: 'myapp.MyPanel'
});
Ext.define('myapp.MyPanel', {
extend: 'Ext.panel.Panel',
title: "My Form Panel",
layout: 'fit',
defaultFocus: '#fldxyz',
items: [{
xtype: 'form',
layout: 'anchor',
items: [{
xtype: 'textfield',
fieldLabel: 'Name',
value: 'Indigo',
id: 'fldxyz',
selectOnFocus: true
}, {
xtype: 'textfield',
fieldLabel: 'Last',
value: 'Montoya'
}]
}],
listeners: {
afterrender: function(formPanel) {
formPanel.focus();
}
}
});
I have a proxy store that retrieves information from a webservice, I would like to show that information in a Panel in a way like a Grid, in which I set the "dataIndex" parameter to bind in the retrieved data.
How can I achieve this goal without extra coding, is that possible?
Something like this:
Proxy Store:
Ext.define('MyStore', {
extend: 'Ext.data.Store',
alias: 'store.myStore',
model: 'myModel',
autoload: true,
proxy: {
type: <wsType>,
url: <wsUrl>
},
scope: this
});
Panel:
Ext.define('<myPanel>', {
extend: 'Ext.panel.Panel',
...
store: Ext.create(<myStore>),
...
items: [
{
xtype: 'titlePanel',
cls: 'titlePanel',
html: '<div class="titlePanel"><h1>My Title</h1></div>',
},
{
xtype: 'form',
layout: 'vbox',
cls: 'whitePanel',
items: [
{
xtype: 'panel',
layout: 'column',
items: [
{
xtype: 'displayfield',
displayField: 'name',
dataIndex: 'name',
fieldLabel: Ext.locale.start,
name: 'start'
},
...
You don't need Store for displaying a single Record. Proxy can be defined at a model level.
Ext.define('MyApp.model.Contact', {
extend: 'Ext.data.Model',
fields: ['id', 'firstName', 'middleName', 'lastName'],
proxy: {
type: 'ajax',
url: 'contacts.json',
reader: {
type: 'json',
rootProperty: 'data'
}
}
});
Load the model either in view constructor/initComponent or controller init method, once loaded push the record to ViewModel.
initComponent: function() {
this.callParent(arguments);
var me = this;
MyApp.model.Contact.load(1, {
success: function(record, operation) {
me.getViewModel().set('contact', record);
}
})
},
Bind the model property to the display field
items: [{
name: 'firstName',
fieldLabel: 'First Name',
bind: '{contact.firstName}',
xtype: 'displayfield'
}]
And here is the fiddle
https://fiddle.sencha.com/#fiddle/17t2
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.
So I have a grid with two columns, the first has just text, the second needs to have a custom control (with a checkbox and a combo box)
Check the screenie:
Here is a link to a screenie:
The Problem:
When I click update to update the row. The first column gets updated, but the second column doesn't
I naively added a getValue() into my custom control but no luck!! (Note: I'm using row editing plugin)
Here is my code:
Ext.define('MainGrid', {
extend: 'Ext.grid.Panel',
//defs for all the toolbars and buttons
plugins: [rowEditing],
columns: [
{
xtype: 'rownumberer'
},
{
xtype: 'gridcolumn',
text: 'Column Titles',
dataIndex: 'ColumnTitle',
editor: {
xtype: 'textfield',
}
},
{
xtype: 'gridcolumn',
sortable: false,
align: 'center',
dataIndex: 'IssueCondition',
editor: {
xtype: 'reportpopulation'
}]
});
The reportpopulation is the custom control here. Here is the code for it:
Ext.define('SelectPopulation', {
extend: 'Ext.container.Container',
itemId: 'ctrSelectpopulation',
alias: 'widget.reportpopulation',
layout: {
type: 'hbox'
},
initComponent: function () {
//code to add combo box and checkbox snipped
....
},
getValue: function () {
//This doesn't work!
return "Booo";
}
});
So clicking Update doesn't :
Is there something I'm missing?
Should I inherit from FieldBase? Can I use multiple controls and create something like the screenie with FieldBase?
This works, even your getValue() was working, the problem is that you used a custom type value on that grid column (IssueCondition) and did not specified any renderer for it, try something like this:
Ext.define('MainGrid', {
extend: 'Ext.grid.Panel',
height: 300,
plugins: [Ext.create('Ext.grid.plugin.RowEditing', {
clicksToEdit: 1
})],
columns: [{
xtype: 'rownumberer'
}, {
xtype: 'gridcolumn',
text: 'Column Titles',
dataIndex: 'ColumnTitle',
editor: {
xtype: 'textfield'
}
}, {
xtype: 'gridcolumn',
sortable: false,
text: "Issue Condition",
align: 'center',
dataIndex: 'IssueCondition',
width: 200,
editor: {
xtype: 'reportpopulation'
},
renderer: function (v, attr, rec) {
console.info(arguments);
return 'cb: ' + rec.data.IssueCondition.cb + ' combo: ' + rec.data.IssueCondition.combo;
}
}],
store: Ext.create("Ext.data.Store", {
fields: ["ColumnTitle", "IssueCondition"],
proxy: {
type: "memory",
reader: {
type: "json"
}
}
})
});
Ext.define('SelectPopulation', {
extend: 'Ext.container.Container',
itemId: 'ctrSelectpopulation',
alias: 'widget.reportpopulation',
layout: {
type: 'hbox'
},
initComponent: function () {
Ext.apply(this, {
items: [{
xtype: "checkbox"
}, {
xtype: "combobox",
allowBlank: false,
store: [
[0, 'Zero'],
[1, 'One'],
[2, 'Two']
]
}]
});
this.callParent(arguments);
},
getValue: function () {
return {
cb: this.child('checkbox').getValue(),
combo: this.child('combobox').getValue()
};
}
});
Be aware that this is just an example.
Check the Fiddle here
Hope this helps.