PDA

View Full Version : Export Excel file in Extjs



VijayBhaskar
6 Oct 2012, 12:30 AM
Hi...

I'm new to Extjs. I'm trying to export a grid store in extjs 4.1
but i got the error Uncaught ReferenceError: swfobject is not defined

here is my html code


<!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Edit List</title> <link rel="stylesheet" type="text/css" href="../resources/css/ext-all.css" /> <link rel="stylesheet" type="text/css" href="../resources/css/zeeko-layout.css" /> <script type="text/javascript" src="../extjs/ext-all.js"></script> <script type="text/javascript" src="../layout/layout.js"></script> <script type="text/javascript" src="editlist.js"></script> <script type="text/javascript" src="../ux/exporter/Exporter.js"></script> <script type="text/javascript" src="../ux/exporter/downloadify.min.js"></script></head><body></body></html>

Here is my .js code


Ext.Loader.setConfig({enabled: true});Ext.Loader.setPath('Ext.ux', '../ux');
Ext.require([
'*'
]);
Ext.require([
'Ext.ux.exporter.Exporter',
'Ext.ux.exporter.Button'
]);
Ext.BLANK_IMAGE_URL = '../resources/images/common/s.gif';


Ext.onReady(function() {


// Employee Data Model
Ext.regModel('Employee', {
fields: [
{name:'id', type:'int'},
{name:'first_name', type:'string'},
{name:'last_name', type:'string'},
{name:'title', type:'string'}
],

hasMany: {model:'Review', name:'reviews'}
});

// Review Data Model
Ext.regModel('Review', {
fields: [
{name:'review_date', label:'Date', type:'date', dateFormat:'d-m-Y'},
{name:'attendance', label:'Attendance', type:'int'},
{name:'attitude', label:'Attitude', type:'int'},
{name:'communication', label:'Communication', type:'int'},
{name:'excellence', label:'Excellence', type:'int'},
{name:'skills', label:'Skills', type:'int'},
{name:'teamwork', label:'Teamwork', type:'int'},
{name:'employee_id', label:'Employee ID', type:'int'}
],

belongsTo: 'Employee'
});

// Instance of a Data Store to hold Employee records
var employeeStore = new Ext.data.Store({
storeId:'employeeStore',
model:'Employee',
data:[
{id:1, first_name:'Michael', last_name:'Scott', title:'michael.scott@gmail.com'},
{id:2, first_name:'Dwight', last_name:'Schrute', title:'dwight.schrute@gmail.com'},
{id:3, first_name:'Jim', last_name:'Halpert', title:'jim.halpert@gmail.com'},
{id:4, first_name:'Pam', last_name:'Halpert', title:'pam.halpert@gmail.com'},
{id:5, first_name:'Andy', last_name:'Bernard', title:'andy.bernard@gmail.com'},
{id:6, first_name:'Stanley', last_name:'Hudson', title:'stanley.hudson@gmail.com'},
{id:7, first_name:'Phyllis', last_name:'Lapin-Vance', title:'phyllis.lapinvance@gmail.com'},
{id:8, first_name:'Kevin', last_name:'Malone', title:'kevin.malone@gmail.com'},
{id:9, first_name:'Angela', last_name:'Martin', title:'angela.martin@gmail.com'},
{id:10, first_name:'Meredith', last_name:'Palmer', title:'meredith.palmer@gmail.com'}
],
autoLoad:true
});

/**
* App.RadarStore
* @extends Ext.data.Store
* This is a specialized Data Store with dynamically generated fields
* data reformating capabilities to transform Employee and Review data
* into the format required by the Radar Chart.
*
* The constructor demonstrates dynamically generating store fields.
* populateReviewScores() populates the store using records from
* the reviewStore which holds all the employee review scores.
*
* calculateAverageScores() iterates through each metric in the
* review and calculates an average across all available reviews.
*
* Most of the actual data population and updates done by
* addUpdateRecordFromReviews() and removeRecordFromReviews()
* called when add/update/delete events are triggered on the ReviewStore.
*/
Ext.define('App.RadarStore', {
extend: 'Ext.data.Store',

constructor: function(config) {
config = config || {};
var dynamicFields = ['metric', 'avg']; // initalize the non-dynamic fields first


employeeStore.each(function(record){ // loops through all the employees to setup the dynamic fields
dynamicFields.push('eid_' + record.get('id'));
});

Ext.apply(config, {
storeId:'radarStore', // let's us look it up later using Ext.data.StoreMgr.lookup('radarStore')
fields:dynamicFields,
data:[]
});

App.RadarStore.superclass.constructor.call(this, config);
},

addUpdateRecordFromReviews: function(reviews) {
var me = this;

Ext.Array.each(reviews, function(review, recordIndex, all) { // add a new radarStore record for each review record
var eid = 'eid_' + review.get('employee_id'); // creates a unique id for each employee column in the store

review.fields.each(function(field) {

if(field.name !== "employee_id" && field.name !== "review_date") { // filter out the fields we don't need
var metricRecord = me.findRecord('metric', field.name); // checks for an existing metric record in the store
if(metricRecord) {
metricRecord.set(eid, review.get(field.name)); // updates existing record with field value from review
} else {
var newRecord = {}; // creates a new object we can populate with dynamic keys and values to create a new record
newRecord[eid] = review.get(field.name);
newRecord['metric'] = field.label;
me.add(newRecord);
}
}
});
});

this.calculateAverageScores(); // update average scores
},

/**
* Calculates an average for each metric across all employees.
* We use this to create the average series always shown in the Radar Chart.
*/
calculateAverageScores: function() {
var me = this; // keeps the store in scope during Ext.Array.each
var reviewStore = Ext.data.StoreMgr.lookup('reviewStore');

var Review = Ext.ModelMgr.getModel('Review');

Ext.Array.each(Review.prototype.fields.keys, function(fieldName) { // loop through the Review model fields and calculate average scores
if(fieldName !== "employee_id" && fieldName !== "review_date") { // ignore non-score fields
var avgScore = Math.round(reviewStore.average(fieldName)); // takes advantage of Ext.data.Store.average()
var record = me.findRecord('metric', fieldName);

if(record) {
record.set('avg', avgScore);
} else {
me.add({metric:fieldName, avg:avgScore});
}
}
});
},

populateReviewScores: function() {
var reviewStore = Ext.data.StoreMgr.lookup('reviewStore');
this.addUpdateRecordFromReviews(reviewStore.data.items); // add all the review records to this store
},

removeRecordFromReviews: function(reviews) {
var me = this;
Ext.Array.each(reviews, function(review, recordIndex, all) {
var eid = 'eid_' + review.get('employee_id');

me.each(function(record) {
delete record.data[eid];
});
});

// upate average scores
this.calculateAverageScores();
}
}); // end App.RadarStore definition


/** Creates an instance of App.RadarStore here so we
* here so we can re-use it during the life of the app.
* Otherwise we'd have to create a new instance everytime
* refreshRadarChart() is run.
*/
var radarStore = new App.RadarStore();

var reviewStore = new Ext.data.Store({
storeId:'reviewStore',
model:'Review',
data:[
{review_date:'01-04-2011', attendance:10, attitude:6, communication:6, excellence:3, skills:3, teamwork:3, employee_id:1},
{review_date:'01-04-2011', attendance:6, attitude:5, communication:2, excellence:8, skills:9, teamwork:5, employee_id:2},
{review_date:'01-04-2011', attendance:5, attitude:4, communication:3, excellence:5, skills:6, teamwork:2, employee_id:3},
{review_date:'01-04-2011', attendance:8, attitude:2, communication:4, excellence:2, skills:5, teamwork:6, employee_id:4},
{review_date:'01-04-2011', attendance:4, attitude:1, communication:5, excellence:7, skills:5, teamwork:5, employee_id:5},
{review_date:'01-04-2011', attendance:5, attitude:2, communication:4, excellence:7, skills:9, teamwork:8, employee_id:6},
{review_date:'01-04-2011', attendance:10, attitude:7, communication:8, excellence:7, skills:3, teamwork:4, employee_id:7},
{review_date:'01-04-2011', attendance:10, attitude:8, communication:8, excellence:4, skills:8, teamwork:7, employee_id:8},
{review_date:'01-04-2011', attendance:6, attitude:4, communication:9, excellence:7, skills:6, teamwork:5, employee_id:9},
{review_date:'01-04-2011', attendance:7, attitude:5, communication:9, excellence:4, skills:2, teamwork:4, employee_id:10}
],
listeners: {
add:function(store, records, storeIndex) {
var radarStore = Ext.data.StoreMgr.lookup('radarStore');

if(radarStore) { // only add records if an instance of the rardarStore already exists
radarStore.addUpdateRecordFromReviews(records); // add a new radarStore records for new review records
}
}, // end add listener
update: function(store, record, operation) {
radarStore.addUpdateRecordFromReviews([record]);
},
remove: function(store, records, storeIndex) {
// update the radarStore and regenerate the radarChart
Ext.data.StoreMgr.lookup('radarStore').removeRecordFromReviews(records);

} // end remove listener
}
});

/**
* App.PerformanceRadar
* @extends Ext.chart.Chart
* This is a specialized Radar Chart which we use to display employee
* performance reviews.
*
* The class will be registered with an xtype of 'performanceradar'
*/
/*Ext.define('App.PerformanceRadar', {
extend: 'Ext.chart.Chart',
alias: 'widget.performanceradar', // register xtype performanceradar
constructor: function(config) {
config = config || {};

this.setAverageSeries(config); // make sure average is always present

Ext.apply(config, {
id:'radarchart',
theme:'Category2',
animate:true,
store: Ext.data.StoreMgr.lookup('radarStore'),
margin:'0 0 50 0',
width:350,
height:500,
insetPadding:80,
legend:{
position: 'bottom'
},
axes: [{
type:'Radial',
position:'radial',
label:{
display: true
}
}]
}); // end Ext.apply

App.PerformanceRadar.superclass.constructor.call(this, config);

}, // end constructor

setAverageSeries: function(config) {
var avgSeries = {
type: 'radar',
xField: 'metric',
yField: 'avg',
title: 'Avg',
labelDisplay:'over',
showInLegend: true,
showMarkers: true,
markerCfg: {
radius: 5,
size: 5,
stroke:'#0677BD',
fill:'#0677BD'
},
style: {
'stroke-width': 2,
'stroke':'#0677BD',
fill: 'none'
}
}

if(config.series) {
config.series.push(avgSeries); // if a series is passed in then append the average to it
} else {
config.series = [avgSeries]; // if a series isn't passed just create average
}
}

});*/ // end Ext.ux.Performance radar definition

/**
* App.EmployeeDetail
* @extends Ext.Panel
* This is a specialized Panel which is used to show information about
* an employee and the reviews we have on record for them.
*
* This demonstrates adding 2 custom properties (tplMarkup and
* startingMarkup) to the class. It also overrides the initComponent
* method and adds a new method called updateDetail.
*
* The class will be registered with an xtype of 'employeedetail'
*/
Ext.define('App.EmployeeDetail', {
extend: 'Ext.panel.Panel',
// register the App.EmployeeDetail class with an xtype of employeedetail
alias: 'widget.employeedetail',
// add tplMarkup as a new property
tplMarkup: [
'<b>{first_name}&nbsp;{last_name}</b>&nbsp;&nbsp;',
'Title: {title}<br/><br/>',
'<b>Last Review</b>&nbsp;&nbsp;',
'Attendance:&nbsp;{attendance}&nbsp;&nbsp;',
'Attitude:&nbsp;{attitude}&nbsp;&nbsp;',
'Communication:&nbsp;{communication}&nbsp;&nbsp;',
'Excellence:&nbsp;{excellence}&nbsp;&nbsp;',
'Skills:&nbsp;{skills}&nbsp;&nbsp;',
'Teamwork:&nbsp;{teamwork}'
],

height:90,
bodyPadding: 7,
// override initComponent to create and compile the template
// apply styles to the body of the panel
initComponent: function() {
this.tpl = new Ext.Template(this.tplMarkup);

// call the superclass's initComponent implementation
App.EmployeeDetail.superclass.initComponent.call(this);
}
});

Ext.define('App.ReviewWindow', {
extend: 'Ext.window.Window',


constructor: function(config) {
config = config || {};
Ext.apply(config, {
title:'Add contact',
width:320,
height:420,
margin:'110 50 50 50',
items:[{
xtype:'form',
id:'employeereviewcomboform',
fieldDefaults: {
labelAlign: 'left',
labelWidth: 90,
anchor: '100%'
},
bodyPadding:5,
items:[{
xtype:'fieldset',
title:'Contact Info',
items:[{
xtype:'hiddenfield',
name:'employee_id'
},{
xtype:'textfield',
name:'first_name',
fieldLabel:'First Name',
allowBlank:false
},{
xtype:'textfield',
name:'last_name',
fieldLabel:'Last Name',
allowBlank:false
},{
xtype:'textfield',
name:'title',
fieldLabel:'Title',
allowBlank:false
}]
},{
xtype:'fieldset',
title:'Performance Review',
items:[{
xtype:'datefield',
name:'review_date',
fieldLabel:'Review Date',
format:'d-m-Y',
maxValue: new Date(),
value: new Date(),
allowBlank:false
},{
xtype:'slider',
name:'attendance',
fieldLabel:'Attendance',
value:5,
increment:1,
minValue:1,
maxValue:10
},{
xtype:'slider',
name:'attitude',
fieldLabel:'Attitude',
value:5,
minValue: 1,
maxValue: 10
},{
xtype:'slider',
name:'communication',
fieldLabel:'Communication',
value:5,
increment:1,
minValue:1,
maxValue:10
},{
xtype:'numberfield',
name:'excellence',
fieldLabel:'Excellence',
value:5,
minValue: 1,
maxValue: 10
},{
xtype:'numberfield',
name:'skills',
fieldLabel:'Skills',
value:5,
minValue: 1,
maxValue: 10
},{
xtype:'numberfield',
name:'teamwork',
fieldLabel:'Teamwork',
value:5,
minValue: 1,
maxValue: 10
}]
}]
}],
buttons:[{
text:'Cancel',
width:80,
handler:function() {
this.up('window').close();
}
},
{
text:'Save',
width:80,
handler:function(btn, eventObj) {
var window = btn.up('window');
var form = window.down('form').getForm();

if (form.isValid()) {
window.getEl().mask('saving data...');
var vals = form.getValues();
var employeeStore = Ext.data.StoreMgr.lookup('employeeStore');
var currentEmployee = employeeStore.findRecord('id', vals['employee_id']);

// look up id for this employee to see if they already exist
if(vals['employee_id'] && currentEmployee) {
currentEmployee.set('first_name', vals['first_name']);
currentEmployee.set('last_name', vals['last_name']);
currentEmployee.set('title', vals['title']);

var currentReview = Ext.data.StoreMgr.lookup('reviewStore').findRecord('employee_id', vals['employee_id']);
currentReview.set('review_date', vals['review_date']);
currentReview.set('attendance', vals['attendance']);
currentReview.set('attitude', vals['attitude']);
currentReview.set('communication', vals['communication']);
currentReview.set('excellence', vals['excellence']);
currentReview.set('skills', vals['skills']);
currentReview.set('teamwork', vals['teamwork']);
} else {
var newId = employeeStore.getCount() + 1;

employeeStore.add({
id: newId,
first_name: vals['first_name'],
last_name: vals['last_name'],
title: vals['title']
});

Ext.data.StoreMgr.lookup('reviewStore').add({
review_date: vals['review_date'],
attendance: vals['attendance'],
attitude: vals['attitude'],
communication: vals['communication'],
excellence: vals['excellence'],
skills: vals['skills'],
teamwork: vals['teamwork'],
employee_id: newId
});
}
window.getEl().unmask();
window.close();
}
}
}]
}); // end Ext.apply

App.ReviewWindow.superclass.constructor.call(this, config);

} // end constructor

});



// adds a record to the radar chart store and
// creates a series in the chart for selected employees


function refreshEmployeeDetails(employees) {
var detailsPanel = Ext.getCmp('detailspanel');
var reviewStore = Ext.data.StoreMgr.lookup('reviewStore');
var items = [];

for(var index = 0; index < employees.length; index++) {
var templateData = Ext.applyIf(employees[index].data, reviewStore.findRecord('employee_id', employees[index].get('id')).data);
var employeePanel = new App.EmployeeDetail({
title:employees[index].get('first_name') + ' ' + employees[index].get('last_name'),
data:templateData // combined employee and latest review dataTransfer
});
items.push(employeePanel);
}

detailsPanel.getEl().mask('updating details...');
detailsPanel.removeAll();
detailsPanel.add(items);
detailsPanel.getEl().unmask();
}

// sets Up Checkbox Selection Model for the Employee Grid
var checkboxSelModel = new Ext.selection.CheckboxModel();

var viewport = new Ext.container.Viewport({
id:'mainviewport',
// sets up Ext.layout.container.Border
items: [{
width: 1300,
height: 530,
margin:'110 50 50 50',
/*autoScroll:true,*/
title:'Edit list',
tbar:[
{
text:'Add Contact',
tooltip:'Add a new contact',
iconCls:'addping',
handler:function() { // display a window to add a new employee
new App.ReviewWindow().show();
}
}
],
items:[
{
xtype:'grid',
id: 'gridId',
uses: [
'Ext.ux.exporter.Exporter'
],
store:Ext.data.StoreMgr.lookup('employeeStore'),
tbar : [
{
xtype: 'exporterbutton',
store: employeeStore
}
],
height:300,
columns:[{
text:'First Name',
dataIndex:'first_name',
flex:2
},
{
text:'Last Name',
dataIndex:'last_name',
flex:2
},
{
text:'Email Address',
dataIndex:'title',
flex:2
},
{
xtype:'actioncolumn',
width:45,
items:[{
icon:'../resources/images/common/edit.png',
tooltip:'Edit Contact',
handler:function(grid, rowIndex, colIndex) {
var employee = grid.getStore().getAt(rowIndex);
var review = reviewStore.findRecord('employee_id', employee.get('id'));
var win = new App.ReviewWindow({hidden:true});
var form = win.down('form').getForm();
form.loadRecord(employee);
form.loadRecord(review);
win.show();
}
},
{
icon:'../resources/images/common/delete.png',
tooltip:'Delete Contact',
width:75,
handler:function(grid, rowIndex, colIndex) {
Ext.Msg.confirm('Remove contact?', 'Are you sure you want to remove this contact?',
function(choice) {
if(choice === 'yes') {
var reviewStore = Ext.data.StoreMgr.lookup('reviewStore');

var employee = grid.getStore().getAt(rowIndex);
var reviewIndex = reviewStore.find('employee_id', employee.get('id'));
reviewStore.removeAt(reviewIndex);
grid.getStore().removeAt(rowIndex);
}
}
);
}
}]
}],
// selModel: new Ext.selection.CheckboxModel(),
columnLines: true,
viewConfig: {stripeRows:true},
listeners:{
selectionchange:function(selModel, selected) {
refreshEmployeeDetails(selected);
}
}
},{
xtype:'container',
id:'detailspanel',
layout:{
type:'vbox',
align:'stretch',
autoSize:true
}
}]
}] // mainviewport items array ends here
});
});


I download export plug from https://github.com/iwiznia/Ext.ux.Exporter

T (https://github.com/iwiznia/Ext.ux.Exporter)hanks

skirtle
6 Oct 2012, 3:38 AM
For more info on swfobject see here:

http://docs.sencha.com/ext-js/4-1/#!/api/Ext.flash.Component

VijayBhaskar
6 Oct 2012, 8:32 PM
Thanks skirtle definitely i will try it :)

indahys
6 Dec 2012, 6:03 PM
Hi, I have a problem while converting grid to excel. I am using CI and Extjs. I apply HTML format while displaying items on grid. Example : I write a list in a grid column so I use <br /> tag, but I have a problem while converting to excel. the column consist of <br /> tag.

here is my code :
Controller :
function get_promosi_cetak(){
$peg_id=json_decode($_GET['idpeg']);
$this->load->model('m_jabatan');
$record=array();
$o=array();
for($i=0;$i<count($peg_id);$i++){
$a=0;
$aksi = $this->m_jabatan->get_cetak_promosi($peg_id[$i]);
//$data=$aksi->first_row();
foreach($aksi->result() as $row){
$record['jabatan']=isset($row->jabatan)?$row->jabatan:'';
$record['tmt_jab']=isset($row->tmt_jab)?$row->tmt_jab:'';
$record['jabatan']=$record['jabatan'].'<br />'.$record['tmt_jab'];
$record['nama']=isset($row->nama)?$row->nama:'';
$record['ttl']=isset($row->ttl)?$row->ttl:'';
$record['usia']=isset($row->usia)?$row->usia:'';
$record['nip']=isset($row->nip)?$row->nip:'';
$record['nama']=$record['nama'].'<br />'.$record['ttl'].'<br />'.$record['usia'].'<br />NIP. '.$record['nip'];
$record['pangkat']=isset($row->pangkat)?$row->pangkat:'';
$record['tmt_pangkat']=isset($row->tmt_pangkat)?$row->tmt_pangkat:'';
$record['mk_pangkat']=isset($row->mk_pangkat)?$row->mk_pangkat:'';
$record['pangkat']=$record['pangkat'].' '.$record['tmt_pangkat'].'<br />'.'('.$record['mk_pangkat'].')';
$record['tmt_eselon']=isset($row->tmt_eselon)?$row->tmt_eselon:'';
$record['mk_eselon']=isset($row->mk_eselon)?$row->mk_eselon:'';
$record['eselon']=$record['tmt_eselon'].'<br />'.'('.$record['mk_eselon'].')';
$record['eselon1']=isset($row->mk_eselon_skrg)?$row->mk_eselon_skrg:'';
$record['no']=$a+1;
$a++;
}

$o[] = $record;
}
echo json_encode($o);
}

here I attach an example. I want to get the format like second image (after), but I get the first (before). Anyone know how to solve my problem? thank you

ananthk
9 Oct 2013, 5:54 PM
Did you get this to work? If so please let me know

Thanks!



Unanswered: Export Excel file in Extjs

Hi...

I'm new to Extjs. I'm trying to export a grid store in extjs 4.1
but i got the error Uncaught ReferenceError: swfobject is not defined

here is my html code
HTML Code:

<!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Edit List</title> <link rel="stylesheet" type="text/css" href="../resources/css/ext-all.css" /> <link rel="stylesheet" type="text/css" href="../resources/css/zeeko-layout.css" /> <script type="text/javascript" src="../extjs/ext-all.js"></script> <script type="text/javascript" src="../layout/layout.js"></script> <script type="text/javascript" src="editlist.js"></script> <script type="text/javascript" src="../ux/exporter/Exporter.js"></script> <script type="text/javascript" src="../ux/exporter/downloadify.min.js"></script></head><body></body></html>
Here is my .js code
Code:

Ext.Loader.setConfig({enabled: true});Ext.Loader.setPath('Ext.ux', '../ux');Ext.require([ '*']);Ext.require(['Ext.ux.exporter.Exporter','Ext.ux.exporter.Button']);Ext.BLANK_IMAGE_URL = '../resources/images/common/s.gif';Ext.onReady(function() { // Employee Data Model Ext.regModel('Employee', { fields: [ {name:'id', type:'int'}, {name:'first_name', type:'string'}, {name:'last_name', type:'string'}, {name:'title', type:'string'} ], hasMany: {model:'Review', name:'reviews'} }); // Review Data Model Ext.regModel('Review', { fields: [ {name:'review_date', label:'Date', type:'date', dateFormat:'d-m-Y'}, {name:'attendance', label:'Attendance', type:'int'}, {name:'attitude', label:'Attitude', type:'int'}, {name:'communication', label:'Communication', type:'int'}, {name:'excellence', label:'Excellence', type:'int'}, {name:'skills', label:'Skills', type:'int'}, {name:'teamwork', label:'Teamwork', type:'int'}, {name:'employee_id', label:'Employee ID', type:'int'} ], belongsTo: 'Employee' }); // Instance of a Data Store to hold Employee records var employeeStore = new Ext.data.Store({ storeId:'employeeStore', model:'Employee', data:[ {id:1, first_name:'Michael', last_name:'Scott', title:'michael.scott@gmail.com'}, {id:2, first_name:'Dwight', last_name:'Schrute', title:'dwight.schrute@gmail.com'}, {id:3, first_name:'Jim', last_name:'Halpert', title:'jim.halpert@gmail.com'}, {id:4, first_name:'Pam', last_name:'Halpert', title:'pam.halpert@gmail.com'}, {id:5, first_name:'Andy', last_name:'Bernard', title:'andy.bernard@gmail.com'}, {id:6, first_name:'Stanley', last_name:'Hudson', title:'stanley.hudson@gmail.com'}, {id:7, first_name:'Phyllis', last_name:'Lapin-Vance', title:'phyllis.lapinvance@gmail.com'}, {id:8, first_name:'Kevin', last_name:'Malone', title:'kevin.malone@gmail.com'}, {id:9, first_name:'Angela', last_name:'Martin', title:'angela.martin@gmail.com'}, {id:10, first_name:'Meredith', last_name:'Palmer', title:'meredith.palmer@gmail.com'} ], autoLoad:true }); /** * App.RadarStore * @extends Ext.data.Store * This is a specialized Data Store with dynamically generated fields * data reformating capabilities to transform Employee and Review data * into the format required by the Radar Chart. * * The constructor demonstrates dynamically generating store fields. * populateReviewScores() populates the store using records from * the reviewStore which holds all the employee review scores. * * calculateAverageScores() iterates through each metric in the * review and calculates an average across all available reviews. * * Most of the actual data population and updates done by * addUpdateRecordFromReviews() and removeRecordFromReviews() * called when add/update/delete events are triggered on the ReviewStore. */ Ext.define('App.RadarStore', { extend: 'Ext.data.Store', constructor: function(config) { config = config || {}; var dynamicFields = ['metric', 'avg']; // initalize the non-dynamic fields first employeeStore.each(function(record){ // loops through all the employees to setup the dynamic fields dynamicFields.push('eid_' + record.get('id')); }); Ext.apply(config, { storeId:'radarStore', // let's us look it up later using Ext.data.StoreMgr.lookup('radarStore') fields:dynamicFields, data:[] }); App.RadarStore.superclass.constructor.call(this, config); }, addUpdateRecordFromReviews: function(reviews) { var me = this; Ext.Array.each(reviews, function(review, recordIndex, all) { // add a new radarStore record for each review record var eid = 'eid_' + review.get('employee_id'); // creates a unique id for each employee column in the store review.fields.each(function(field) { if(field.name !== "employee_id" && field.name !== "review_date") { // filter out the fields we don't need var metricRecord = me.findRecord('metric', field.name); // checks for an existing metric record in the store if(metricRecord) { metricRecord.set(eid, review.get(field.name)); // updates existing record with field value from review } else { var newRecord = {}; // creates a new object we can populate with dynamic keys and values to create a new record newRecord[eid] = review.get(field.name); newRecord['metric'] = field.label; me.add(newRecord); } } }); }); this.calculateAverageScores(); // update average scores }, /** * Calculates an average for each metric across all employees. * We use this to create the average series always shown in the Radar Chart. */ calculateAverageScores: function() { var me = this; // keeps the store in scope during Ext.Array.each var reviewStore = Ext.data.StoreMgr.lookup('reviewStore'); var Review = Ext.ModelMgr.getModel('Review'); Ext.Array.each(Review.prototype.fields.keys, function(fieldName) { // loop through the Review model fields and calculate average scores if(fieldName !== "employee_id" && fieldName !== "review_date") { // ignore non-score fields var avgScore = Math.round(reviewStore.average(fieldName)); // takes advantage of Ext.data.Store.average() var record = me.findRecord('metric', fieldName); if(record) { record.set('avg', avgScore); } else { me.add({metric:fieldName, avg:avgScore}); } } }); }, populateReviewScores: function() { var reviewStore = Ext.data.StoreMgr.lookup('reviewStore'); this.addUpdateRecordFromReviews(reviewStore.data.items); // add all the review records to this store }, removeRecordFromReviews: function(reviews) { var me = this; Ext.Array.each(reviews, function(review, recordIndex, all) { var eid = 'eid_' + review.get('employee_id'); me.each(function(record) { delete record.data[eid]; }); }); // upate average scores this.calculateAverageScores(); } }); // end App.RadarStore definition /** Creates an instance of App.RadarStore here so we * here so we can re-use it during the life of the app. * Otherwise we'd have to create a new instance everytime * refreshRadarChart() is run. */ var radarStore = new App.RadarStore(); var reviewStore = new Ext.data.Store({ storeId:'reviewStore', model:'Review', data:[ {review_date:'01-04-2011', attendance:10, attitude:6, communication:6, excellence:3, skills:3, teamwork:3, employee_id:1}, {review_date:'01-04-2011', attendance:6, attitude:5, communication:2, excellence:8, skills:9, teamwork:5, employee_id:2}, {review_date:'01-04-2011', attendance:5, attitude:4, communication:3, excellence:5, skills:6, teamwork:2, employee_id:3}, {review_date:'01-04-2011', attendance:8, attitude:2, communication:4, excellence:2, skills:5, teamwork:6, employee_id:4}, {review_date:'01-04-2011', attendance:4, attitude:1, communication:5, excellence:7, skills:5, teamwork:5, employee_id:5}, {review_date:'01-04-2011', attendance:5, attitude:2, communication:4, excellence:7, skills:9, teamwork:8, employee_id:6}, {review_date:'01-04-2011', attendance:10, attitude:7, communication:8, excellence:7, skills:3, teamwork:4, employee_id:7}, {review_date:'01-04-2011', attendance:10, attitude:8, communication:8, excellence:4, skills:8, teamwork:7, employee_id:8}, {review_date:'01-04-2011', attendance:6, attitude:4, communication:9, excellence:7, skills:6, teamwork:5, employee_id:9}, {review_date:'01-04-2011', attendance:7, attitude:5, communication:9, excellence:4, skills:2, teamwork:4, employee_id:10} ], listeners: { add:function(store, records, storeIndex) { var radarStore = Ext.data.StoreMgr.lookup('radarStore'); if(radarStore) { // only add records if an instance of the rardarStore already exists radarStore.addUpdateRecordFromReviews(records); // add a new radarStore records for new review records } }, // end add listener update: function(store, record, operation) { radarStore.addUpdateRecordFromReviews([record]); }, remove: function(store, records, storeIndex) { // update the radarStore and regenerate the radarChart Ext.data.StoreMgr.lookup('radarStore').removeRecordFromReviews(records); } // end remove listener } }); /** * App.PerformanceRadar * @extends Ext.chart.Chart * This is a specialized Radar Chart which we use to display employee * performance reviews. * * The class will be registered with an xtype of 'performanceradar' */ /*Ext.define('App.PerformanceRadar', { extend: 'Ext.chart.Chart', alias: 'widget.performanceradar', // register xtype performanceradar constructor: function(config) { config = config || {}; this.setAverageSeries(config); // make sure average is always present Ext.apply(config, { id:'radarchart', theme:'Category2', animate:true, store: Ext.data.StoreMgr.lookup('radarStore'), margin:'0 0 50 0', width:350, height:500, insetPadding:80, legend:{ position: 'bottom' }, axes: [{ type:'Radial', position:'radial', label:{ display: true } }] }); // end Ext.apply App.PerformanceRadar.superclass.constructor.call(this, config); }, // end constructor setAverageSeries: function(config) { var avgSeries = { type: 'radar', xField: 'metric', yField: 'avg', title: 'Avg', labelDisplay:'over', showInLegend: true, showMarkers: true, markerCfg: { radius: 5, size: 5, stroke:'#0677BD', fill:'#0677BD' }, style: { 'stroke-width': 2, 'stroke':'#0677BD', fill: 'none' } } if(config.series) { config.series.push(avgSeries); // if a series is passed in then append the average to it } else { config.series = [avgSeries]; // if a series isn't passed just create average } } });*/ // end Ext.ux.Performance radar definition /** * App.EmployeeDetail * @extends Ext.Panel * This is a specialized Panel which is used to show information about * an employee and the reviews we have on record for them. * * This demonstrates adding 2 custom properties (tplMarkup and * startingMarkup) to the class. It also overrides the initComponent * method and adds a new method called updateDetail. * * The class will be registered with an xtype of 'employeedetail' */ Ext.define('App.EmployeeDetail', { extend: 'Ext.panel.Panel', // register the App.EmployeeDetail class with an xtype of employeedetail alias: 'widget.employeedetail', // add tplMarkup as a new property tplMarkup: [ '<b>{first_name}&nbsp;{last_name}</b>&nbsp;&nbsp;', 'Title: {title}<br/><br/>', '<b>Last Review</b>&nbsp;&nbsp;', 'Attendance:&nbsp;{attendance}&nbsp;&nbsp;', 'Attitude:&nbsp;{attitude}&nbsp;&nbsp;', 'Communication:&nbsp;{communication}&nbsp;&nbsp;', 'Excellence:&nbsp;{excellence}&nbsp;&nbsp;', 'Skills:&nbsp;{skills}&nbsp;&nbsp;', 'Teamwork:&nbsp;{teamwork}' ], height:90, bodyPadding: 7, // override initComponent to create and compile the template // apply styles to the body of the panel initComponent: function() { this.tpl = new Ext.Template(this.tplMarkup); // call the superclass's initComponent implementation App.EmployeeDetail.superclass.initComponent.call(this); } }); Ext.define('App.ReviewWindow', { extend: 'Ext.window.Window', constructor: function(config) { config = config || {}; Ext.apply(config, { title:'Add contact', width:320, height:420, margin:'110 50 50 50', items:[{ xtype:'form', id:'employeereviewcomboform', fieldDefaults: { labelAlign: 'left', labelWidth: 90, anchor: '100%' }, bodyPadding:5, items:[{ xtype:'fieldset', title:'Contact Info', items:[{ xtype:'hiddenfield', name:'employee_id' },{ xtype:'textfield', name:'first_name', fieldLabel:'First Name', allowBlank:false },{ xtype:'textfield', name:'last_name', fieldLabel:'Last Name', allowBlank:false },{ xtype:'textfield', name:'title', fieldLabel:'Title', allowBlank:false }] },{ xtype:'fieldset', title:'Performance Review', items:[{ xtype:'datefield', name:'review_date', fieldLabel:'Review Date', format:'d-m-Y', maxValue: new Date(), value: new Date(), allowBlank:false },{ xtype:'slider', name:'attendance', fieldLabel:'Attendance', value:5, increment:1, minValue:1, maxValue:10 },{ xtype:'slider', name:'attitude', fieldLabel:'Attitude', value:5, minValue: 1, maxValue: 10 },{ xtype:'slider', name:'communication', fieldLabel:'Communication', value:5, increment:1, minValue:1, maxValue:10 },{ xtype:'numberfield', name:'excellence', fieldLabel:'Excellence', value:5, minValue: 1, maxValue: 10 },{ xtype:'numberfield', name:'skills', fieldLabel:'Skills', value:5, minValue: 1, maxValue: 10 },{ xtype:'numberfield', name:'teamwork', fieldLabel:'Teamwork', value:5, minValue: 1, maxValue: 10 }] }] }], buttons:[{ text:'Cancel', width:80, handler:function() { this.up('window').close(); } }, { text:'Save', width:80, handler:function(btn, eventObj) { var window = btn.up('window'); var form = window.down('form').getForm(); if (form.isValid()) { window.getEl().mask('saving data...'); var vals = form.getValues(); var employeeStore = Ext.data.StoreMgr.lookup('employeeStore'); var currentEmployee = employeeStore.findRecord('id', vals['employee_id']); // look up id for this employee to see if they already exist if(vals['employee_id'] && currentEmployee) { currentEmployee.set('first_name', vals['first_name']); currentEmployee.set('last_name', vals['last_name']); currentEmployee.set('title', vals['title']); var currentReview = Ext.data.StoreMgr.lookup('reviewStore').findRecord('employee_id', vals['employee_id']); currentReview.set('review_date', vals['review_date']); currentReview.set('attendance', vals['attendance']); currentReview.set('attitude', vals['attitude']); currentReview.set('communication', vals['communication']); currentReview.set('excellence', vals['excellence']); currentReview.set('skills', vals['skills']); currentReview.set('teamwork', vals['teamwork']); } else { var newId = employeeStore.getCount() + 1; employeeStore.add({ id: newId, first_name: vals['first_name'], last_name: vals['last_name'], title: vals['title'] }); Ext.data.StoreMgr.lookup('reviewStore').add({ review_date: vals['review_date'], attendance: vals['attendance'], attitude: vals['attitude'], communication: vals['communication'], excellence: vals['excellence'], skills: vals['skills'], teamwork: vals['teamwork'], employee_id: newId }); } window.getEl().unmask(); window.close(); } } }] }); // end Ext.apply App.ReviewWindow.superclass.constructor.call(this, config); } // end constructor }); // adds a record to the radar chart store and // creates a series in the chart for selected employees function refreshEmployeeDetails(employees) { var detailsPanel = Ext.getCmp('detailspanel'); var reviewStore = Ext.data.StoreMgr.lookup('reviewStore'); var items = []; for(var index = 0; index < employees.length; index++) { var templateData = Ext.applyIf(employees[index].data, reviewStore.findRecord('employee_id', employees[index].get('id')).data); var employeePanel = new App.EmployeeDetail({ title:employees[index].get('first_name') + ' ' + employees[index].get('last_name'), data:templateData // combined employee and latest review dataTransfer }); items.push(employeePanel); } detailsPanel.getEl().mask('updating details...'); detailsPanel.removeAll(); detailsPanel.add(items); detailsPanel.getEl().unmask(); } // sets Up Checkbox Selection Model for the Employee Grid var checkboxSelModel = new Ext.selection.CheckboxModel(); var viewport = new Ext.container.Viewport({ id:'mainviewport', // sets up Ext.layout.container.Border items: [{ width: 1300, height: 530, margin:'110 50 50 50', /*autoScroll:true,*/ title:'Edit list', tbar:[ { text:'Add Contact', tooltip:'Add a new contact', iconCls:'addping', handler:function() { // display a window to add a new employee new App.ReviewWindow().show(); } } ], items:[ { xtype:'grid', id: 'gridId', uses: [ 'Ext.ux.exporter.Exporter' ], store:Ext.data.StoreMgr.lookup('employeeStore'), tbar : [ { xtype: 'exporterbutton', store: employeeStore } ], height:300, columns:[{ text:'First Name', dataIndex:'first_name', flex:2 }, { text:'Last Name', dataIndex:'last_name', flex:2 }, { text:'Email Address', dataIndex:'title', flex:2 }, { xtype:'actioncolumn', width:45, items:[{ icon:'../resources/images/common/edit.png', tooltip:'Edit Contact', handler:function(grid, rowIndex, colIndex) { var employee = grid.getStore().getAt(rowIndex); var review = reviewStore.findRecord('employee_id', employee.get('id')); var win = new App.ReviewWindow({hidden:true}); var form = win.down('form').getForm(); form.loadRecord(employee); form.loadRecord(review); win.show(); } }, { icon:'../resources/images/common/delete.png', tooltip:'Delete Contact', width:75, handler:function(grid, rowIndex, colIndex) { Ext.Msg.confirm('Remove contact?', 'Are you sure you want to remove this contact?', function(choice) { if(choice === 'yes') { var reviewStore = Ext.data.StoreMgr.lookup('reviewStore'); var employee = grid.getStore().getAt(rowIndex); var reviewIndex = reviewStore.find('employee_id', employee.get('id')); reviewStore.removeAt(reviewIndex); grid.getStore().removeAt(rowIndex); } } ); } }] }], // selModel: new Ext.selection.CheckboxModel(), columnLines: true, viewConfig: {stripeRows:true}, listeners:{ selectionchange:function(selModel, selected) { refreshEmployeeDetails(selected); } } },{ xtype:'container', id:'detailspanel', layout:{ type:'vbox', align:'stretch', autoSize:true } }] }] // mainviewport items array ends here });});
I download export plug from https://github.com/iwiznia/Ext.ux.Exporter


(https://github.com/iwiznia/Ext.ux.Exporter)