Binding grid to form without viewmodel - extjs

To binding between a grid and a form I use something like:
viewModel: {
type: 'viewermodel'
},
items: [{
xtype: 'grid',
title: 'Grid: click on the grid rows',
itemId:'myGridItemId',
flex: 1.2,
margin: '0 10 0 0',
bind:{
store:'{mystore}',
selection:'{users}'
},
columns: [
{ text: 'Name', dataIndex: 'name', flex:0.5 },
{ text: 'Email', dataIndex: 'email', flex: 1 },
{ text: 'Cars', dataIndex: 'cars', flex: 1 }
]
},
FIDDLE: https://fiddle.sencha.com/#fiddle/1is6&view/editor
Problem: the store is not in a viewmodel but in the store's app folder (App.store.MyStore).
Is there any way, in this case, of binding selection: '{users}' from record grid to form fields? Something like:
store:'MyStore',
bind:{
selection:'{users}'
},

You need to add MyStore to your application's store config.
Here's the updated fiddle. You'll see in Ext.application I've added stores: ['MyStore']

Related

Grids with store and viewmodel in Extjs-5.1.2

I'm just getting started with ExtJS and am looking to create a grid which will populate based on data it will receive from the server as a json. I'm having trouble understanding the architecture and how to separate information to correctly display on the grid view, since it seems much more complex and involved than if I were working in something like vanilla Javascript.
I currently have it working when the data has been hardcoded into the view here:
Ext.define('MyApp.view.main.Main', {
extend: 'Ext.container.Viewport',
requires: [
'MyApp.view.main.MainController',
'MyApp.view.main.MainModel',
'Ext.panel.Panel',
'Ext.grid.Panel'
],
/*
...Other containers and panels here
*/
xtype: 'grid',
width: '99%',
flex: 1,
store: {
fields:['name', 'email', 'address', 'hobby', 'notes'],
data:[
{ name: 'Rate', email: "rate#example.com",
address: "382 Kilmanjaro", hobby: "tennis", notes: "Lorem ipsum dolor.."},
{ name: 'Jimjam', email: "jim#example.com",
address: "889 McKinley", hobby: "none"}
],
proxy: {
type: 'memory'
}
},
columns: [
{ text: 'Name', dataIndex: 'name' },
{ text: 'Email', dataIndex: 'email'},
{ text: 'address', dataIndex: 'address' },
{ text: 'hobby', dataIndex: 'hobby'},
{ text: 'Notes', dataIndex: 'notes', flex: 1, cellWrap: true}
]
}]
But I'd like to move the store and data out of the view, and ideally read from a json file (and later a GET request). Other questions I've seen have had a bunch of different methods to approach this but I find them all rather confusing and none seem to work for me, especially with different versions (I'm using ExtJS 5.1.2).
I'd appreciate any pointers in the right direction as to where to place my store and data and how to bind it correctly to the view. I think my main issues lie with usage of the associated Controller.js, Model.js, and Store.js files, and what kind of information goes in them.
Just updating that I got it working! I checked out the kitchen sink examples and old documentation from ExtJS4 to understand how the architecture worked.
My main issue was being new to ExtJS and attempting to create something while learning it at the same time, so I hope any other newbies can wrap their heads around this!
The basic idea is that there is a Model, Store, and View, and I've understood it as a Model being a class, a Store being a Collection of those objects, and the view being a display. A Store depends on a Model, and a View (at least, the grid I was building) depends on a Store. I tried to avoid separating too many views, writing javascript functions and overriding initComponent, but this was exactly what I had to do to get it working.
So I've written architecture like this:
model/Person.js:
Ext.define('MyApp.model.Person', {
extend: 'Ext.data.Model',
fields:['name', 'email', 'address', 'hobby', 'notes'],
proxy: {
type: 'ajax',
url: 'data/UserResponse.json',
reader: {
type: 'json',
rootProperty: 'results',
}
}
store/Persons.js:
Ext.define('MyApp.store.Persons', {
extend: 'Ext.data.Store',
/*Model for the store*/
requires: 'MyApp.model.Person',
model: 'MyApp.model.Person'
});
view/main/Main.js:
Ext.define('MyApp.view.main.Main', {
extend: 'Ext.container.Viewport',
requires: [
'Ext.panel.Panel',
'Ext.grid.Panel',
'MyApp.view.main.PersonGrid'
],
xtype: 'container',
controller: 'main',
viewModel: {
type: 'main'
},
layout: {
type: 'vbox',
align: 'center'
},
width: '100%',
items:
[{
xtype: 'panel',
flex: 1,
border: false,
width: '98%',
layout: {
type: 'vbox',
align: 'stretch'
},
items:
[{
xtype: 'panel',
height: 30,
margin: '5 5 1 5',
flex: 1,
width: '98%',
layout: {
type: 'vbox',
align: 'center'
},
title: 'Users - USA',
collapsible: true,
items: [
{
xtype: 'person-grid',
rootVisible: true,
store: 'Persons'
}]
}]
}]
});
view/main/PersonGrid.js:
Ext.define('MyApp.view.main.PersonGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.person-grid',
xtype: 'grid',
width: '99%',
flex: 1,
columns: [
{ text: 'Name', dataIndex: 'name' },
{ text: 'Email', dataIndex: 'email'},
{ text: 'address', dataIndex: 'address' },
{ text: 'hobby', dataIndex: 'hobby'},
{ text: 'Notes', dataIndex: 'notes', flex: 1, cellWrap: true}
],
initComponent: function() {
//initComponent taken from http://examples.sencha.com/extjs/5.1.0/examples/kitchensink/#xml-grid
var me = this;
this.callParent();
this.on('afterlayout', this.loadStore, this, {
delay: 1,
single: true
});
},
loadStore: function() {
this.getStore().load();
}
});
data/UserResponse.json:
{
"success": true,
"results":[
{ name: 'Rate', email: "rate#example.com",
address: "382 Kilmanjaro", hobby: "tennis", notes: "Lorem ipsum dolor.."},
{ name: 'Jimjam', email: "jim#example.com",
address: "889 McKinley", hobby: "none"}
]
}
app/Application.js:
Ext.define('MyApp.Application', {
extend: 'Ext.app.Application',
models: ['Person'],
stores: ['Persons'],
launch: function () {
// TODO - Launch the application
}
});
The main difference from what I was attempting before was to separate the grid into its own view, and edit the initComponent function here to load the store (which I wasn't doing earlier)! Earlier, I had the grid and its configurations nested within the items{} array of other components and trying to autoLoad the store, or utilize storeId and other methods of binding store to grid.
The above architecture works perfectly for me, and I am able to read data from my json file and mock responses from server! :)

Bind store size to table's header

I have ExtJS application and I want to implement displaying total number of records in the header.
ViewModel:
Ext.define('AppName.view.main.MainModel', {
extend: 'Ext.app.ViewModel',
// ...
stores: {
users: Ext.create("AppName.store.UsersStore")
}
});
Binding to view
Ext.define('AppName.view.main.UsersPanel', {
extend: 'Ext.panel.Panel',
// ...
items:[{
bind : {
title : 'Users ({users.data.length})'
},
items: [{
listeners : {
cellclick : 'OnSelectUser'
},
xtype: 'grid', columns: [
{ text: 'Full Name', dataIndex: 'fullName', flex: 2},
{ text: 'Address', dataIndex: 'address', flex: 1},
{ text: 'Sex', dataIndex: 'sex', flex: 1},
{ text: 'Date Of Birth', dataIndex: 'dob', flex: 1}
],
bind: '{users}'
}]
}]
});
And this works after first loading of records to Store by code
OnSearchButtonClick: function () {
var me = this,
usersStore = me.getViewModel().get('users');
usersStore.load();
}
But when I remove records from store by code
var me = this,
usersStore = me.getViewModel().get('users');
usersStore.loadData([], false);
or by
usersStore.removeAll()
then only table is cleared but not header.
So I have a question: how can I bind store size?
try with sync on the store after removing records.
usersStore.removeAll();
usersStore.sync();
sometimes binding not refresh binded components because new or removed records are not synched in the store

EXTJS : How to display multiple grid on single page?

I would like to display multiple grid on page, grid should not overlap each other and all the grid should populate horizontally , every request should create a new grid on the same page so that we can compare the data very easily across the grid. Please help me how to do that in the EXTJS. I don't have much idea of EXTJS.
do you want to generate grids dynamically or their quantity is static? can you provide you code to work with?
is your answer as simple as :
{
xtype:"container",
height: 353,
width: 994,
layout: {
type: 'hbox',
align: 'stretch'
},
items: [
{
xtype: 'gridpanel',
flex: 1,
title: 'My Grid Panel',
columns: [
{
xtype: 'gridcolumn',
dataIndex: 'string',
text: 'String'
}
]
},
{
xtype: 'gridpanel',
flex: 1,
title: 'My Grid Panel',
columns: [
{
xtype: 'gridcolumn',
dataIndex: 'string',
text: 'String'
}
]
},
{
xtype: 'gridpanel',
flex: 1,
title: 'My Grid Panel',
columns: [
{
xtype: 'gridcolumn',
dataIndex: 'string',
text: 'String'
}
]
}
]
}
Create a main panel and set its layout to hbox,then add grids dynamically to that panel's item list on user's request

How to add selectable option to combobox without affecting the store on Sencha ExtJS 5?

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-"});

bind a grid to form without using mvc

I am trying to bind a grid data to a form in extjs. when i click on a grid row, the details should be populated in form. Can i do that in a simple way without using MVC. I have wrote the below code. help me further. Thank you
// JavaScript Document
Ext.require('Ext.data.Store');
Ext.require('Ext.grid.Panel');
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [ 'id','name', 'email', 'phone' ]
});
Ext.onReady(function() {
var userStore = Ext.create('Ext.data.Store', {
model: 'User',
data: [
{ id: '1', name: 'srb', email: 'srb#gmail.com', phone: '555-111-1224' },
{ id: '2', name: 'srv', email: 'srv#gmail.com', phone: '555-222-1254' }
]
});
Ext.create('Ext.grid.Panel', {
renderTo: Ext.getBody(),
store: userStore,
width: 400,
title: 'All Users',
columns: [
{
text: 'Id',
dataIndex: 'id' ,
flex: 1
},
{
text: 'Name',
dataIndex: 'name',
flex: 2
},
{
text: 'Email Address',
flex: 3,
dataIndex: 'email',
},
{
text: 'Phone Number',
flex: 2,
dataIndex: 'phone'
}
],
listeners : {
itemclick: function(dv, record, item, index, e) {
var nm= record.get('name');
}
},
});
Ext.create('Ext.form.FieldSet',{
renderTo: Ext.getBody(),
margin: '0 0 0 10',
title:'User details',
defaults: {
width: 240,
labelWidth: 90
},
defaultType: 'textfield',
items: [{
fieldLabel: 'Id',
name: 'id'
},{
fieldLabel: 'Name',
name: 'name'
},{
fieldLabel: 'Email Id',
name: 'email'
},{
fieldLabel: 'Phone Number',
name: 'phone'
}]
});
});
Use Ext.form.Panel instead of Ext.form.FieldSet. Field set is more of a decorating container. The form panel provides support for loading / saving data from the form, etc.
Then you need a way to access your form panel in your click event. The absolute simplest is to set an id on the form, and use Ext.getCmp to get a ref to the form. Since you've already got the record there, you can just use the loadRecord method of the form panel.
And you'll be done! Be happy to have named your model & form fields the same ;)
The final call in the event listener will look like this:
Ext.getCmp('myForm').loadRecord(record);
what version of extjs are you using?
you don't seem to have a form defined or instantiated.
in your grid's itemclick event handler, you need to get a reference to the form, and call form.loadRecord with the passed in record (2nd argument):
itemclick: function(dv, record, item, index, e) {
var form = getAReferenceToTheFormObject();
form.loadRecord(record);
}
example:
http://jsfiddle.net/4TSDu/74/

Resources