How to use global functions/Utility Class in EXTJS - extjs

My code structure is as follows->
MyApp-> app -> controller, model, store, shared (util-> Utility.js), view
I have created the following Utility Class
Ext.define('MyApp.shared.util.Utilities', {
myFunction : function (val, meta, rec) {
//do something
return val;
}
});
I am trying to call the myFunction while rendering a column in my grid as follows ->
Ext.define('MyApp.view.MyGrid', {
extend: 'Ext.grid.Panel',
initComponent: function() {
var rendererFn = Ext.create('MyApp.shared.util.Utilities');
this.columns = [{
text: 'Col1',
dataIndex: 'col1'
renderer: rendererFn.myFunction
};
this.store = new MyApp.store.MyStore();
this.store.load();
this.callParent(arguments);
}
});
This works fine but I want to know if this is the correct way of using global functions.

A better way would be to declare your class a singleton:
Ext.define('MyApp.shared.util.Utilities', {
singleton: true,
myFunction : function (val, meta, rec) {
//do something
return val;
}
});
Ext.define('MyApp.view.MyGrid', {
extend: 'Ext.grid.Panel',
initComponent: function() {
this.columns = [{
text: 'Col1',
dataIndex: 'col1'
renderer: MyApp.shared.util.Utilities.myFunction
}];
this.store = new MyApp.store.MyStore();
this.store.load();
this.callParent(arguments);
}
});

Related

Nested initComponent not working

I have a window(Ext.window.Window) in which I have pane in card layout. I am adding grid dynamically to the panels item as:
Ext.define('Example.view.ProcessInfoLayout',{
extend: 'Ext.window.Window',
requires: [
'Ext.layout.container.Card',
'Example.view.SubProcessController',
'Example.view.Info'
],
xtype: 'app--processinfolayout',
controller: 'main-content-subprocesscontroller',
layout: 'fit',
initComponent: function(){
this.callParent();
this.header = {
titlePosition: 0,
items:[{
xtype: 'button',
text: 'Resubmission',
glyph: 'xf0e2#FontAwesome',
tooltip: 'Resubmit',
listeners: {
click: 'ResubmissionClick'
}
}]
};
console.log('thisw')
this.items = []
this.add({
xtype: 'panel',
frame: false,
border: false,
itemId: 'v6panel',
layout: {
type:'card',
deferredRender: true
},
defaultListenerScope: true,
bbar: ['->',
{
itemId: 'card-prev',
text: '« Previous',
handler: 'showPrevious',
disabled: true
},
{
itemId: 'card-next',
text: 'Next »',
handler: 'showNext'
}
],
items: [],
initComponent: function() {
var me = this;
me.callParent();
me.store = Ext.getStore('app-main-store-' + me.up('app-main-processinfolayout').processData.id);
if (!me.store) {
me.store = Ext.create('Example.store.ProcessInfo', {
storeId: 'app-main-store-' + me.up('app-main-processinfolayout').processData.id,
room: me.up('app-main-processinfolayout').processData.id
});
me.store.proxy.url = Ext.String.format(me.store.proxy.url,
me.up('app-main-processinfolayout').processData.id);
}
me.store.on('load', function(store, records, successful, eOpts) {
console.log('####')
me.fireEvent('refreshProcessInfoLayoutView', me, records);
});
},
listeners:{
beforerender: function(obj) {
console.log('Hey Australia')
obj.store.load();
},
refreshProcessInfoLayoutView: 'refreshProcessInfoLayoutView',
scope: 'this'
},
refreshProcessInfoLayoutView: function(obj, records) {
console.log('thise')
console.log(records[0].data.processes)
if (records[0].data.v6_processes) {
for (elem in records[0].data.processes) {
var subprocessInfo = {
xtype: 'app-main-cycle-info',
processId: records[0].data.processes[elem],
itemId: 'card-' + elem
};
obj.add(subprocessInfo);
}
}
},
showNext: function () {
this.doCardNavigation(1);
},
showPrevious: function (btn) {
this.doCardNavigation(-1);
},
doCardNavigation: function (incr) {
var me = this;
var l = me.getLayout();
var i = l.activeItem.id.split('card-')[1];
var next = parseInt(i, 10) + incr;
l.setActiveItem(next);
me.down('#card-prev').setDisabled(next===0);
me.down('#card-next').setDisabled(next===this.down('#v6panel').store.getCount() - 1);
}
})
}
})
It prints console log upto thisw . After that it gives error as...Uncaught TypeError: me.items.insert is not a function. What I am doing wrong. Please suggest.
Don't do this.callParent(); in your initComponent before specifying this.header and this.items. Do it after. This is because once you've called this.callParent(); your component is instantiated, therefore trying stuff like this.items = [] just screws things up.
Also, instead of:
this.items = [];
this.add({stuff});
do:
this.items = [{stuff}];
When dealing with nested items and initComponent functions, you can use the xhooks config so that callParent() can work properly :
Ext.define('Example.view.ProcessInfoLayout', {
// ...
xhooks: {
initComponent: function(){
this.callParent();
// ...
this.add({
xtype: 'panel',
// ...
items: [],
initComponent: function() {
// ...
}
});
}
}
});
Have a look at the Ext.Component constructor method.

Extjs4 class listeners and functions

In this code, there are many existing function, but I have to start to make some extended ExtJS class using that functions.
How can I add an existing function to a listener of a class?
For example:
Ext.define("My.Grid", {
extend: 'Ext.grid.Panel',
//...
initComponent: function() {
//...
Ext.apply(this, {
//...
tbar: [{
xtype: 'button',
icon: 'img/x.png',
handler: function(){
// need to call randomOtherFunction here
}
}]
});
}
});
function randomOtherFunction () {
// ...
}
Yessss, it works! :) ... and I hope, it will be good until the old other functions go to an object.
function randomOtherFunction () {
// ...
}
My.functions = {
randomOtherFunction: function () {
randomOtherFunction();
}
};
Ext.define("My.Grid", {
extend: 'Ext.grid.Panel',
//...
initComponent: function() {
//...
Ext.apply(this, {
//...
tbar: [{
xtype: 'button',
icon: 'img/x.png',
handler: function(){
My.functions.randomOtherFunction();
}
}]
});
}
});
You have to check the scope and use it to call the handler function.
Try the below
Ext.define("My.Grid", {
extend: 'Ext.grid.Panel',
//...
initComponent: function() {
//...
Ext.apply(this, {
//...
tbar: [{
xtype: 'button',
icon: 'img/x.png',
scope:this,
handler:this.randomOtherFunction
}]
});
}
});
function randomOtherFunction () {
// ...
}
Hope it helps you.

Rally API 2 inspect contents of a model

I have some code that is pulling a Release model back and displaying in a grid, this is working fine, but I cannot work out how to inspect what is in the returned model.
What I would like is to get the contents of the model in some kind of object that I can reorganise or drill into as I see fit (in this case the release model).
If I add a component and just dump the model into the html it is not returning the contents as I would expect.
Rally.data.ModelFactory.getModel({
type: 'Release',
success: function(model) {
this.add({
xtype: 'component',
html: model
});
this.grid = this.add({
xtype: 'rallygrid',
model: model,
columnCfgs: [
'FormattedID',
'Name',
'RevisionHistory' ],
storeConfig: {
filters: queryFilters
}
});
},
scope: this
});
If I dig into the ExtJS docs it seems I should be able to do something like getData() on the model to return the contents but this is not working.
Inspection in the debugger tells me I have a "Rally.domain.v2.0.project.10098485624.Release" object but I can't see how to simply access the list of items in the object. Obviously there is a way because passing this model to a grid component will display it quite happily.
The debugger for this object shows me a number of further functions to call but I have no idea which one or how to use it
...
getArtifactMappings: function () {
getCollectionFields: function () {
getCustomFields: function () {
getField: function (fieldName) {
getFields: function () {
getFieldsByName: function (fieldNames) {
getName: function () {
getNonCollectionFields: function () {
getPermissionLevels: function (permission) {
getProxy: function () {
etc...
The Rally docs indicate I should be able to call getData() on a model https://help.rallydev.com/apps/2.0rc2/doc/#!/api/Rally.data.Model but it looks like the ModelFactory.getModel() is not returning a type that has a getData() method
A model is a class, and a record is an instance of that class.
getData() will work on a record.
There are static methods that would work on the actual model, but getData() is not one of them.
Here is a fragment from the code below:
_onDataLoaded: function(store, data){
_.each(data, function(record){
var r = record.getData();
console.log('release', r);
This code builds a grid of Releases filtered by project and ReleaseStartDate. I noticed that in your code you want to display model information, maybe for debug purposes, by actually modifying the dom. I would prefer to use console.log, but in the example below I did both. I used a border layout with a footer, and set html proprety of the container in the footer to JSON.stringify(r)
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
layout:'border',
defaults: {
collapsible: true,
split: true,
bodyStyle: 'padding:15px',
},
items: [{
title: 'data',
region:'south',
itemId: 'd',
margins: '5 0 0 0',
cmargins: '5 5 0 0'
},{
title: 'Releases',
itemId: 'r',
collapsible: false,
region:'center',
margins: '5 0 0 0'
}] ,
launch: function() {
var context = this.getContext();
var projectId = context.getProject().ObjectID;
var millisecondsInDay = 86400000;
var currentDate = new Date();
var startDate = new Date(currentDate - millisecondsInDay*90); //in the last 90 days
var startDateUTC = startDate.toISOString();
Ext.create('Rally.data.WsapiDataStore', {
model: 'Release',
fetch: ['Name','ReleaseStartDate','ReleaseDate', 'State'],
filters: [
{
property: 'ReleaseStartDate',
operator: '>',
value: startDateUTC
},
{
property: 'Project',
operator: '=',
value: '/project/'+ projectId
}
],
autoLoad: true,
listeners: {
load: this._onDataLoaded,
scope: this
}
});
},
_onDataLoaded: function(store, data){
var text = '';
_.each(data, function(record){
var r = record.getData();
console.log('release', r);
text = text + JSON.stringify(r);
});
console.log('text', text);
this.down('#d').add({
xtype:'container',
html: text
});
if (!this.down('#g')) {
this.down('#r').add({
xtype: 'rallygrid',
store: store,
itemId: 'g',
columnCfgs: [
{
text: 'Name', dataIndex: 'Name'
},
{
text: 'State', dataIndex: 'State'
},
{
text: 'Start Date', dataIndex: 'ReleaseStartDate', flex:1
},
{
text: 'Release Date', dataIndex: 'ReleaseDate',flex:1
}
]
});
}
else{
(this.down('#g')).reconfigure(store);
}
}
});

Extjs 4 - How to up to parent component in initComponent function

I define a gridpanel like
Ext.define('Example', {
extend: 'Ext.grid.Panel',
alias: 'myGrid',
store:Ext.create('Ext.data.Store', {
fields: [
{name: 'name'}
]
}),
initComponent: function() {
alert(this.up('window').title); //but error like this.up(...) is undefined
this.callParent(arguments);
}
...
And I create a window have a item above
items: {
xtype: 'myGrid'
}
I want to get some thing in parent componet. How to up to parent component in initComponent function. Thanks
initComponent: function() {
var me = this;
this.callParent(arguments);
me.on('render', function() {
alert(me.up('window').title);
});
}
You can't. The component must first be instantiated before it is added to the container. You can override the onAdded template method, which will get called when the component is added to a container:
Ext.define('Foo',
extend: 'Ext.Component',
onAdded: function(ct) {
this.callParent(arguments);
console.log('Added to', ct);
}
});

Ext.getCmp is not working in ExtJS4

I am trying to create a component and access it inside controller. But while accessing the component by id, it is not returning the component. It always returns undefined. Please find below the code.
enter code here
//Component creation in view layer as below
Ext.define('MyApp.view.performance.grid.IFrameGridCmp', {
extend: 'Ext.panel.Panel',
alias: 'widget.crMainPanel',
id:'mainPanelId',
layout: {
align: 'stretch',
type: 'vbox'
},
border:0,
resizable: false,
forceFit: true,
autoWidth: true,
initComponent: function() {
Ext.apply(this, {
items: [
{
xtype:'panel',
flex:.02,
border:0
},
{
xtype:'crHeaderPanel',
flex:.05
},
{
xtype: 'crUpperPanel',
flex: 0.93
},
Ext.create('Ext.Component', {
autoEl: {
tag: 'iframe',
cls: 'x-hidden',
src: Ext.SSL_SECURE_URL
},
id:'FileDownloader',
height:0,
listeners: {
afterrender: function () {
this.getEl().on('load', function () {
console.log('loaded download frame');
});
}
},
load: function(config){
var e = this.getEl();
e.dom.src = config.url + (config.params ? '?' + Ext.urlEncode(config.params) : '');
e.dom.onload = function() {
Ext.getBody().unmask();
if(e.dom.contentDocument.body.childNodes[0].wholeText == '404') {
Ext.Msg.show({
title: 'Attachment missing',
msg: 'The document you are after can not be found on the server.',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
});
}
};
}
})
]
});
this.callParent(arguments);
}
});
========================================
enter code here
//Accessing the controller as below in controller
views: ['performance.grid.IFrameGridCmp'],
//The below line gives error
var downloader = Ext.getCmp('FileDownloader');
downloader.load({
url: '/APXUI/data/json/xls?exportData='+Ext.JSON.encode(records)
});
Well, the view is not created at the time you are calling Ext.getCmp()
Note that views: ['performance.grid.IFrameGridCmp'], is only a sort of binding that view to the controller, which means the controller will create a getter for you, nothing more. You still need to instantiate the view by calling .create(); or Ext.widget('crMainPanel')
In you controller use control for example to handle it:
me.control({
'crMainPanel #FileDownloader': {
afterrender: me.addDownloader
}
});
Don't use Ext.getCmp() it is really slow and you will have many issues with that.
Don't use id - better use itemId.
Why you need to call this from controller?

Resources