Defining store vs creating store in extjs - extjs

I would like to know the pros and cons of define store VS create store in ExtJS. Which approach is better in case of many entities?

If you define a store, the store (if globally located and not inside a viewmodel) will be globally registered automatically on the app launch process if you require it..
Instead if you create a store runtime, you need to register it before using it like a global store (using regStore funcion)
In my opinion there aren't really differences in final functionality, in some cases you need to create a store runtime, in others you don't need it, and you can define it..
The real difference is the order on your code files.. is obviously better to define stores globally to check them if needed during code development..
In fact, if you need to update your code after a while, you could be disappointed to search a store inside your lines of code. Instead if you have a file that defines it you can search it more fast..
Obviously, defining a store, you also provide a class, that can be utilized again and again when you need.
So, in short words, define a store if you need it in more than one position in your code, if you need to use it twice or more, and if you need order on your code folders.
Instead, create runtime a store, when you need only like a temp one, during a function execution.
Quick tip: if you need a store only inside a single view, define it in the viewmodel of the view, is the better think on using a viewmodel architecture.

There really are not two cases, in which there is no better or worse.
The question is the means of applying to the problem that you need to solve.
100% of the cases recommend you set up your store, maybe the question you could ask is how you should instantiate your store.
90% of cases I instantiate the store globally defined in an application by the default template to be used.
The 10% case that I end up using in cases as a master / detail functionality, where I need to open multiple instances of the same functionality. If I do not instantiate the store for each instance of functionality, each change or load in the store will be replicated in the other open functionality, and this is a serious error for the user.
Set your store globally.
Here's an example of instantiating locally.
/**
* #class Litus.view.segundaviaBoleto.Grid
* Listagem de 2º via de boletos
*/
Ext.define('Litus.view.segundaviaBoleto.Grid',{
extend: 'Ext.grid.Panel',
xtype: '2viaBoleto-Grid',
require: [
'Litus.store.segundaviaBoleto.Store'
],
allowPaging: false,
multiSelect: false,
viewConfig: {
stripeRows: true,
enableTextSelection: true
},
/**
* #method initComponent
* Tratamento da inicialização do componente.
* #protected
*/
initComponent: function () {
var me = this;
//Locally instantiated the store at the start of the grid component, because this grid is opened several times.
me.store = Ext.create('Litus.store.segundaviaBoleto.Store');
Ext.applyIf(me, {
columns: [{
text: 'Documento',
width: 190,
sortable: false,
dataIndex: 'NumeroDocumento',
align: 'center',
style: 'text-align: center'
}, {
xtype: 'datecolumn',
text: 'Vencimento',
width: 130,
sortable: false,
dataIndex: 'DataVencimento',
format: 'd/m/Y',
align: 'center',
style: 'text-align: center'
}, {
xtype: 'numbercolumn',
text: '(R$) Valor',
width: 130,
align: 'right',
sortable: false,
dataIndex: 'ValorAtual',
style: 'text-align: center',
format: '#,##0.00'
}, {
text: 'Empresa',
flex: 1,
sortable: false,
dataIndex: 'Descricao',
align: 'left',
style: 'text-align: center'
}]
});
me.callParent(arguments);
}
});

Related

Send value from one view to another ExtJS 4

I want to send value from one view to another one, I have a code that's work in ExtJS 6 but not in ExtJS 4.
This is from the first one:
var test = Ext.create('test.text', {
delayedRenderTo: container_id,
id: 'messageBox-' + meta.rowIndex,
viewModel: {
data: {
value: value
}
}
});
and we bind it like this:
Ext.define('test.text', {
extend: 'Ext.Panel',
layout: {
type: 'vbox',
align: 'stretch',
overflow: 'scroller',
},
items: [{
xtype: 'textareafield',
grow: true,
growMin: 30,
growMax: 120,
disabled: true,
fullscreen: true,
bind: {
value: '{value}',
},
fieldStyle: 'font-weight:bold;'
}]
});
What is the alternative for ExtJS 4 ?
ViewModels were introduced in Ext JS 5 which is why it doesn't work in Ext JS 4.
To do it in Ext JS 4, you'd have to find the component (the textareafield in this case) and then execute the setter (setValue for this example). It's all manual in Ext JS 4.
Getting the component depends on many things but the best way is to use ComponentQuery and depends where the code executing this would be. First, you'd have to get your test.text instance and then use comp.child('textareafield'). I cannot give you a silver bullet example as it depends on many factors but using component's down, child, query, up methods a good start and they all have different purposes.

Composite component with a border layout in ExtJS

I was wondering how I should start making a custom composite component. One that has a border layout, but for which its items show in the center region of the border layout. The following image shows what I'm trying to achieve:
In pseudo-code this would be:
Ext.define('App.custom.ContentView', {
extend: 'Ext.container.Container',
xtype: 'contentview',
layout: 'border',
northCmp: ..., // Custom north region component.
westCmp: ..., // Custom west region component.
centerCmp: ..., // Placeholder for the items it will have.
items: [] // Filled in by each implementation, shown in the center region.
});
Ext.create('App.custom.ContentView', {
layout: 'vbox', // Applies to center region of 'contentview'.
items: [
// Items that go into the center region of the 'contentview'.
]
});
I have looked through the ExtJS source code, and viewed a couple of examples at the Sencha Market; but I have not found an obvious example that does not include a lot of duplicate code.
Any help, or nudge in the right direction, would be greatly appreciated! :)
You should not do that. Please, don't let me be misunderstood, your intentions are good but the implementation you describe will grip in some point in the future. I know because I did something similar when I debuted with Ext. The idea of tuning the component declaration to your tastes/need/whatever may seem like a pleasant simplification... Unfortunately, in practice what you want to do is to give another meaning to an existing construct (items in your case). Here's what it will really bring you:
All code external to your application (that includes Ext, and Ext future releases!) will expect components/container to behave the classic way. That is, that the items of a container are really the items it contains, not the items of one of its children. Unexpected behaviour is to be expected.
You'll inevitably want to customize this component in some ways. You've already started, with the layout of the center region. If you rewrite the way the component work, you'll have to write some kind of config proxy to any feature you want to use. Big burden instead of a little saving. Doesn't worth it.
And finally, in some time you'll have forgotten all about what you've done with this component. And you'll have to debug your code just to understand what it is supposed to do (that is, before debugging the real issues).
Sorry for lecturing... All that being said, that doesn't mean there's not a way to come close to what you want without falling prey to reframing the framework.
Here's how I would do it (fiddle):
Ext.define('My.custom.BorderContainer', {
extend: 'Ext.container.Container'
// xtype is used in Ext3 and Touch... Ext4 uses aliases
,alias: 'widget.contentview'
,layout: 'border'
,items: [{
region: 'north'
,xtype: 'container'
,html: "<h1>Some header</h1>"
,style: 'background-color: lightblue;'
},{
region: 'west'
,xtype: 'container'
,split: true
,html: "<h1>Some menu</h1>"
,style: 'background-color: purple;'
},{
region: 'center'
,xtype: 'container'
}]
/**
* Configuration of the center panel.
*
* #cfg {Object/Ext.Component}
*/
,center: null
,initComponent: function() {
var center = this.center;
if (center) {
if (center instanceof Ext.Component) {
center.region = 'center';
} else {
// never modify a passed config object, that could
// break the expectations of the using code
center = Ext.clone(center);
// apply default config, including the region
center = Ext.applyIf(center, this.items[2]);
}
this.items[2] = center;
}
// else use default config, already in place
this.callParent(arguments);
}
});
Notice how I added a new center config option instead of trying to recycle existing ones (items, layout, etc.). That allows me to put anything I want, customized to the bone, and with usual syntax, in that. Future me and coworkers will probably send me chocolates for that! For example:
Ext.widget('contentview', {
renderTo: Ext.getBody()
,height: 300
,center: {
layout: {
type: 'vbox'
,align: 'center'
}
,defaults: {
xtype: 'component'
,margin: 10
,padding: 10
}
,items: [{
html: 'Red'
,style: 'background-color: green;'
},{
html: 'Green'
,style: 'background-color: blue;'
},{
html: 'Blue'
,style: 'background-color: red;'
}]
}
});
Ext.widget('contentview', {
renderTo: Ext.getBody()
,height: 300
,center: {
xtype: 'tabpanel'
,tabPosition: 'bottom'
,items: [{
title: 'First Tab'
,html: "I'm empty!"
},{
title: 'Second Tab'
}]
}
});
Ext.widget('contentview', {
renderTo: Ext.getBody()
,height: 300
// passing a component instance instead of a config object
,center: Ext.widget('button', {
text: "Foo"
})
});

ExtJS, oneToMany relationship and nested table

Here, the Sencha team explains how to have a one to many relationship:
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.Store
And you get more in detail here:
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.reader.Reader
where they explain that
"This may be a lot to take in - basically a User has many Orders, each
of which is composed of several OrderItems. Finally, each OrderItem
has a single Product."
Nice.
Now I want to have a Form where there's the user information PLUS a grid of the user's orders (not the MVC framework, just a a derived class of form.Panel).
How can I do this? Here's the beginning of my form.Panel class, where there are only fields. I just want to add to it a datagrid that is linked with Product.
So I create my store, like in the example, Sencha gave, then I create a grid that is linked to a MyFramework.form.Panel, and everything works fine. I just want to make something like a "nested table", a one to many grid in that class, to display the products that belong to the current user.
Any idea how to do this?
Ext.define('MyFramework.form.Panel', {
extend: 'Ext.form.Panel',
alias: 'widget.writerform',
requires: ['Ext.form.field.Text'],
initComponent: function(){
this.addEvents('create');
Ext.apply(this, {
activeRecord: null,
iconCls: 'icon-user',
frame: true,
title: 'User',
defaultType: 'textfield',
bodyPadding: 5,
fieldDefaults: {
anchor: '100%',
width: 500,
labelWidth: 200,
labelAlign: 'right'
},
items: [{
xtype:'tabpanel',
activeTab: 0,
defaults:{
layout: 'fit',
bodyStyle:'padding:10px'
},
items:[{
title:'General information',
defaultType: 'textfield',
items: [{
fieldLabel: 'Titre ',
name: 'titre',
allowBlank: false
},{
fieldLabel: 'Image grande ',
name: 'imgGrande'
}]
},{
title:'Products',
defaultType: 'textfield',
items: [
/*
* Advices/example here!
* I'm stuck!
*/
]
}]
}]
});
this.callParent();
}
});
You can work with the concept of Dynamic Form interacting with an embbed grid.
Of course that doesn't suit your needs right away. My advice, though, is to start from there and try to implement a field that will be related to an embbed grid, in your case a grid of products.
With that said, you wouldn't have a form that is filled by the embbed grid selection, but a single field that gets filled like a ComboBox, but by the grid selection.
Maybe try the Ext.form.LookUp field, a component that I've created that is kinda related to that problem.
This component is not exactly what you are looking for, since it works with single records, like with one to one relationships. But you can try to implement something from there.

Extjs Cloning a panel

panel({}) and all its contents like grid, form and want to render that exact clone to another panel is there a way to do it..is it possible to do it with panel.getEl() or is there any other way...please help
The sra's answer is incorrect. Ext's cloneConfig does exactly what you want it to. http://docs.sencha.com/ext-js/4-1/#!/api/Ext.Component-method-cloneConfig
The following code renders two of the "same" panels to the body.
var panel = Ext.create('Ext.Panel', {
width: 500,
height: 300,
title: "HBoxLayout Panel",
layout: {
type: 'hbox',
align: 'stretch'
},
renderTo: document.body,
items: [{
xtype: 'panel',
title: 'Inner Panel One',
flex: 2
},{
xtype: 'panel',
title: 'Inner Panel Two',
flex: 1
},{
xtype: 'panel',
title: 'Inner Panel Three',
flex: 1
}]
});
var clone = panel.cloneConfig();
I must admit that the old answer was not entirely correct. Cloning of Componments is available since ExtJS2 and can be done via cloneConfig(overrides) which is a instance-method.
This will return a clone of the current instance with the applied overrides (if set). A clean clone will require you to use correct configurations, meaning no instances are created within the config. Here are some information bout this For more details read the Sencha guides
Old answer (only valid if the components to clone configs contains instances instead of plain configurations)
No, there is no buildin way to do this. And you should not try it. Consider to wrap the panel in a function that returns a instance of it (a simple sort of factory).
Edit
Something like this:
Factory.Panel = function (config) {
var defaults = {
labelWidth: 80,
labelAlign: 'left',
layout: 'form',
width: 720,
autoHeight: true,
header: false,
bodyStyle: 'padding:10px 15px;'
};
var cfg = Ext.apply({}, config, defaults);
var cmp = new Panel(cfg);
return cmp;
}
You can add as much function params as you like. This would be a clean way to do it. You just can clone simple object like a record. Note that Factory is a Namespace!

delete a record from grid and database on button click event in ext js

i am using ext js designer with ruby on rails.
i want to delete a record from my grid and database on button click event.
can anyone help me?
thanks...
following is the code of my grid.
xtype: 'grid',
title: 'Products',
store: 'productMaster',
height: 176,
id:'mygrid',
name:'mygrid',
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
rowselect: function(sm, row, rec) {
Ext.getCmp("myform").getForm().loadRecord(rec);
}
}
}),
columns: [
{
xtype: 'gridcolumn',
dataIndex: 'name',
header: 'name',
sortable: true,
width: 100
},
{
xtype: 'gridcolumn',
dataIndex: 'price',
header: 'price',
sortable: true,
width: 100
},
{
xtype: 'gridcolumn',
dataIndex: 'category',
header: 'category',
sortable: true,
width: 100
},
and following is my code of delete button
bbar: {
xtype: 'toolbar',
height: 30,
items: [
{
xtype: 'button',
text: 'Delete',
width: 100,
height: 30,
id:'btnDelete',
handler: function() {
//alert('trying to delete the record...');
var store = Ext.getCmp("mygrid").getStore();
store.removeAt(store.getCount()-1);
}
due to this handler function the last record id deleted but it is deleted from the store not fro the database.i want the record to be deleted from the database also...
thanks...
Before we start: I noticed the configuration object for your grid has
xtype:'grid'
This, by itself, forbids any editing capability and server interactions (besides reading the store), because you are instancing an Ext.grid.GridPanel, while (I think) you need an Ext.grid.EditorGridPanel. For all of the following to run properly, you should change this line to:
xtype:'editorgrid'
First thing I would check is that the store has an id configuration attribute, and it is a configured column of the store reader. If the store cannot identify the record, it will think that the record does not exist, and will not generate a request to the server.
Second thing to check: has your store been configured to generate server requests? That is, is there a line like this in your store config object?
proxy: new Ext.data.HttpProxy({
api:{
read:'readscript.url',
create:'insertscript.url',
update:'updatescript.url',
destroy:'deletescript.url'
}
})
Next, have you defined the "writer" attribute in your store configuration object?
The store config object should have a proxy and a writer attribute to generate proper server requests upon deletion.
To specify a writer for the store you may simply write (for a common Json writer):
writer: new Ext.data.JsonWriter()
and the store will send all the appropriate write requests to the server.
Another painful (not well documented, I think) issue could be the presence of mandatory fields in the store reader. All columns are mandatory by default; to mark a column as "non-mandatory" you must specify (in the store reader column array):
{name:'column_name', allowBlank:true, /* other stuff like 'type' etc. */ }
Probably, when you add a new record to the grid, not all of the columns will be populated.
The store will not generate a server create request until all mandatory columns are populated. Then, if you delete an unsaved record, the store will not generate the destroy request because it will assume that the record "does not exist".

Resources