How to get ExtJs 4 panel to update itself on data refresh - extjs

I'm using ExtJs 4.
I have a panel that looks something like this:
var panel = Ext.create('Ext.panel.Panel',{
title: 'Current Transaction Data',
width: 500,
items:[
{
id: 'field1',
xtype: 'textfield',
label:'Field 1',
},
{
id: 'field 2',
xtype: 'textfield',
label:'Field 1',
}
],
})
I have a function to issue an ajax request that looks something like this:
var myDataObject;
var getData= function(callback){
Ext.Ajax.request({
url: 'MY-URL-TO-GET-DATA',
success: function(response){
myDataObject= Ext.JSON.decode(response.responseText)}})}
What I want to do is that after I retrieve my data object, I want to tell the panel to update with the new data. I'm looking for a call like panel.update(data).
I have seen the update() method on panel, but don't understand how to use it. Do I override it? It says something about using templates, but I haven't found any good examples. I'm not even sure if that's the preferred approach for doing this.
I have done similar type things using grid panel and using a data store. In that case I can call refresh() on the data store, but I don't want to use a grid for this particular problem.

You could use panel.update(data) but that just injects the text as innerHTML effectively, using the configured tpl if necessary. What are the two text fields in your panel for? You could set the text of one of those fields to the data, or add a Ext.form.field.DisplayView to the panel, and set the value of that to the data.
EDIT: As suggested in the comments below, the answer is to subclass and add a method to do the data refresh.

Related

Using Id and itemId in Extjs to access components

In ExtJs Best practices I gone through not to use Id for accessing Ext Components rather use ItemId, I am very new in accessing components using ItemID, does any one can help me in default syntax or the way to access components.
Also on click of yes in a message box I need to disable some components in masked page, whether this can be achieved with the help of ItemID? Please explain.
I feel when using ItemiD it may return array of elements/components, so if need to get an exact component I need to iterate again. I have this ques too....
Basic difference between id and itemId is
When you use an id for a component, there must be a single instance of this component, If you create another instance that has the same id, you will have problems as the DOM is confused.
when you use itemId, it should be unique only within the component's immediate container.the component's container maintains a list of children ids.
so the best practice is to use itemId instead of id
now How to access?
if you use id
Ext.getCmp('id')
or
document.getElementById('id')
or
Ext.ComponentQuery.query("#id")[0]
if you use itemId
parentContainer.getComponent('child_itemId'),
refer following example
e.g
var parentContainer= Ext.create('Ext.panel.Panel', {
initComponent: function(){
Ext.applyIf(me, {
//childrens
items: [{
xtype:'textfield',
itemId:'text'
},
{
xtype:'panel',
itemId:'childpanel',
items:[
{
xtype:'combobox',
itemId:'combo'
}
]
}]
});
this.callParent(arguments);
},
renderTo:Ext.getBody()
})
in above example
for accessing textfield use
parentContainer.getComponent('text');
for accessing combobox use
parentContainer.getComponent('childpanel').getComponent('combo');
or
Ext.ComponentQuery.query("#combo")[0];
this will return array of item with id combo in page
for these you should use unique itemId so you will get the first item you are searching for
or
parentContainer.queryById('combo');
you can also use Ext.util.MixedCollection
var fields = new Ext.util.MixedCollection();
fields.addAll(parentContianer.query('[isFormField]'));
var Combo = fields.get('combo');
Lets suppose you define Panel like below which have a button. Now to access this button you can use Extjs ComponentQuery api. To uniquely identify my button I can use Ext.ComponentQuery.query('myPanel button[itemId=myButton]')[0]. For more details check http://docs-origin.sencha.com/extjs/4.2.2/#!/api/Ext.ComponentQuery
Ext.define('app.view.panel.MyPanel', {
extend: 'Ext.form.Panel',
alias: 'widget.myPanel',
height: 360,
width: 480,
layout:'fit',
title: 'My Panel',
initComponent: function(){
var me =this;
me.items=[{
xtype:'button',
itemId: 'myButton'
...
}]
this.callParent(arguments);
}
})
You can search and access components by using the
Ext.Component.query and passing along the itemId, refer to following links:-
http://training.figleaf.com/tutorials/senchacomplete/chapter2/lesson5/2.cfm
http://devjs.eu/en/how-to-use-ext-component-query-in-ext-js-4/

customizing sencha yes no combo within a specific panel without affecting parent combo box

I need to customize the yes no combo within a specific panel, local to the panel without affecting the parent yesnocombo box configuration. Is there a way to do this?
I am referring to the form I posted earlier in another thread in the Sencha forums, but no one has answered. The url is:
http://www.sencha.com/forum/showthre...ng-Sencha-form
I tried this:
var myNewStore =[
"", "Yes", "Revoke"];
Ext.define('YesNoCombo',{
extend:'Ext.form.ComboBox',
store:myNewStore,
value:'',
emptyText:'Select...',
labelalign:'left',
labelWidth:550,
inputWidth:80,
allowBlank:true,
listeners:{
select:function(comp,record,index){
if(comp.getVelue() == "" || comp.getVale() ==="&nbsp")
comp.setValue(null);
}
}
});
but this broke the format of the form.
Is there a way to create a local combo with custom variables like this:
var UserForm_BlahBlahBlah=Ext.create('YesNoCombo', {
name:"UserForm_BlahBlahBlah",
fieldLabel:"BlahBlahBlah",
values:" Yes" "Revoke",
});
I tried this but it will not work. But you get the idea- It is just creating a local extension within a specific panel with new values.
Is this possible? Or is there a better way that sencha implements customizing the combo box with out affecting the parent class?
Regards,
umbre gachoong
You can easily extend Ext.form.ComboBox class and create your own combo box class. Then you can use your combobox in forms.
In the exmaple I create custom combobox by using its xtype which I defined by alias: 'widget.yesNoCombo'. You can also create instance of custom combobox by var combo = Ext.create('YesNoCombo');
Ext.define('YesNoCombo',{
alias: 'widget.yesNoCombo',
extend:'Ext.form.ComboBox',
store: ["No", "Yes", "Revoke"],
emptyText:'Select...',
allowBlank:true
});
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
items:[
{
xtype: 'yesNoCombo',
fieldLabel:'Yes No Label',
name: 'combo',
},
{
xtype: 'textfield',
fieldLabel: 'Another field',
name: 'anotherField',
},
]
});
See this fiddle https://fiddle.sencha.com/#fiddle/210

How to get an element in a View from a Controller?

I am using Sencha Touch 2,0,1.
I need to get an element from a View in a Controller.
At the moment I use this method, which get the View correctly, but I am not able to get the Item in the View. I do not get any error just test is undefined.
Any ideas?
In the Controller:
var test = this.getDetailView().items['editButton'];
Code in the View:
Ext.define('XXX.view.DetailView',{
...
items: [
{
xtype: 'button',
text: 'Edit XXX',
ui: 'custom-btn-dwn-timetable',
itemId: 'editButton'
}
],
...
}
There are a couple other ways to get the reference to the edit button. You can wire the edit button as a ref like this:
Ext.define('MyApp.Controller', {
extend: 'Ext.app.Controller',
config: {
refs: {
editButton: '#editButton'
}
},
Then in your controller you can call the automatically generated getterthis.getEditButton() to get the actual edit button component.
Another thing you can do is save the edit button as an instance variable on your view like this:
Ext.define('XXX.view.DetailView',{
...
items: [
this.editButton = Ext.widget{(
xtype: 'button',
text: 'Edit XXX',
ui: 'custom-btn-dwn-timetable',
itemId: 'editButton'
)}
],
...
}
So now to access your button in the controller you have to do: this.getDetailView().editButton
In general, if an element is something you access a lot you should have a saved reference to it, rather than querying the DOM (to avoid unnecessary performance hit). Using Ext.getCmp() is also slower due to execution stack (it has to go through the ComponentManager every single time just to get the reference).
You can use Ext.ComponentQuery in this case to get your button:
Ext.ComponentQuery.query('#editButton')[1];
You could try setting your button id to edit and then
Ext.getCmp('edit').hide();

setRenderer() method in Extjs4

Extjs 3.3.1 have the method setRenderer() as
/**
* Sets the rendering (formatting) function for a column.
*/
setRenderer( Number col, Function fn ) : void
Now I don't get any method in ExtJS 4 of setRenderer. So How can I format grid column at runtime in ExtJS 4.
When you're creating your grid you can define the renderer on each column...
Ext.create('Ext.grid.Panel', {
title: 'Grid Sample',
store: Ext.data.StoreManager.lookup('yourStore'),
columns: [
{header: 'Product Description', dataIndex: 'description'},
{header: 'Cost', dataIndex: 'cost', renderer: nameOfRenderFunction },
],
height: 200,
width: 400,
renderTo: Ext.getBody()
});
And then you can define your function in a global scope...
function nameOfRenderFunction(v) {
//do something to v
return v;
}
What I did was set the renderer after the fact. After my application launched, I got the instantiated component and added a renderer in my controller's onLaunch() function like this:
// An example renderer
var myComponentsRenderer = function( value ){
return value++;
};
// Get the instantiated component
var myComponent = Ext.ComponentQuery.query( "#myComponent" )[0];
// Attach the renderer
Ext.override( myComponent, {
renderer : myComponentsRenderer,
});
The reason I like this method is because I am able to put the renderer functions in my controller and keep logic out of my view. It helps me organize my code better.
it looks like the the way to do it is mentioned in passing in this post on the sencha forum.
You can use a grid's reconfigure method to swap in a different list of columns (along with renderers) however this does have the major downside that you'll have to totally respecify the columns in their entirety.
Did you find a better way? I really dont like the fact it forces you to put renderers in a place where they can't be tested and can't access state in a none static way.
However it seems the cure is worse than the disease in this case as you'd end up taking what is very definitely view code out of the view.
Sometimes it feels like they didn't really think about the design of these things very much :(

Extjs Dynamic Grid

I'm trying to create a dynamic grid using ExtJS. The grid is built and displayed when a click event is fired then an ajax request is sent to the server to fetch the columns, records and records definition a.k.a store fields.
Each node could have different grid structure and that depends on the level of the node in the tree.
The only way I came up with so far is :
function showGrid(response, request) {
var jsonData = Ext.util.JSON.decode(response.responseText);
var grid = Ext.getCmp('contentGrid' + request.params.owner);
if (grid) {
grid.destroy();
}
var store = new Ext.data.ArrayStore({
id: 'arrayStore',
fields: jsonData.recordFields,
autoDestroy: true
});
grid = new Ext.grid.GridPanel({
defaults: {
sortable: true
},
id: 'contentGrid' + request.params.owner,
store: store,
columns: jsonData.columns,
//width:540,
//height:200,
loadMask: true
});
store.loadData(jsonData.records);
if (Ext.getCmp('tab-' + request.params.owner)) {
Ext.getCmp('tab-' + request.params.owner).show();
} else {
grid.render('grid-div');
Ext.getCmp('card-tabs-panel').add({
id: 'tab-' + request.params.owner,
title: request.params.text,
iconCls: 'silk-tab',
html: Ext.getDom('grid-div').innerHTML,
closable: true
}).show();
}
}
The function above is called when a click event is fired
'click': function(node) {
Ext.Ajax.request({
url: 'showCtn',
success: function(response, request) {
alert('Success');
showGrid(response, request);
},
failure: function(results, request) {
alert('Error');
},
params: Ext.urlDecode(node.attributes.options);
}
});
}
The problem I'm getting with this code is that a new grid is displayed each time the showGrid function is called. The end user sees the old grids and the new one. To mitigate this problem, I tried destroying the grid and also removing the grid element on each request, and that seems to solve the problem only that records never get displayed this time.
if (grid) {
grid.destroy(true);
}
The behaviour I'm looking for is to display the result of a grid within a tab and if that tab exists replaced the old grid.
Any help is appreciated.
When you are trying to add your grid to the tab like this:
html:Ext.getDom('grid-div').innerHTML,
Ext is not aware of it being a valid grid component. Instead, you are simply adding HTML markup that just happens to look like a grid, but the TabPanel will not be aware that it is a grid component.
Instead you should add the grid itself as the tab (a GridPanel is a Panel and does not need to be nested into a parent panel). You can do so and also apply the needed tab configs like this:
Ext.getCmp('card-tabs-panel').add({
Ext.apply(grid, {
id: 'tab-' + request.params.owner,
title: request.params.text,
iconCls: 'silk-tab',
closable: true
});
}).show();
BTW, constantly creating and destroying grids is not an ideal strategy if you can avoid it. It might be better to simply hide and re-show grids (and reload their data) based on which type of grid is needed if that's possible (assuming the set of grid types is finite).
A potential option is to use the metaData field on the JsonStore that allows dynamic reconfiguring of the grid columns as per new datasets.
From
One of the most helpful blog posts about this that Ive found is this one:
http://blog.nextlogic.net/2009/04/dynamic-columns-in-ext-js-grid.html and the original info is well documented at http://docs.sencha.com/ext-js/3-4/#!/api/Ext.data.JsonReader

Resources