When i try to generate a word cloud using d3,js, the g element is rendered ouside of svg when i give data to it via api call. But when i supply data locally, it is working properly.The angular ts code is below:
import { Component, OnInit } from '#angular/core';
import * as D3 from 'd3';
import { PopulatTopicsService } from '../services/populat-topics.service';
declare let d3: any;
#Component({
selector: 'app-populat-topics',
templateUrl: './populat-topics.component.html',
styleUrls: ['./populat-topics.component.css']
})
export class PopulatTopicsComponent implements OnInit {
constructor(private popularService : PopulatTopicsService){}
//local data- works fine
// data = [
// {text: 'Bob',size:33,cuscolor: '#abaaea'},
// {text: 'Robin',size:12,cuscolor: '#abaaea'},
// {text: 'Anne',size:41,cuscolor: '#abaaea'},
// {text: 'Mark',size:16,cuscolor: '#abaaea'},
// {text: 'Joe',size:39,cuscolor: '#abaaea'}
// ];
network ="FB";
startDate ="01/04/2018";
endDate ="07/04/2018";
brandId ="720";
userId ="20615";
period ="LASTWEEK";
data =[];
wdata = "u gh h xfg fg gf";
ngOnInit() {
this.popularService.wordCloud(this.userId,this.startDate,this.endDate,this.brandId,this.period,this.network).subscribe(res =>
{
console.log(res);
this.data = res;
console.log(this.data['term']);
let cls = this;
// this.data = this.wdata.split(' ').map(function(d) {
// return {text: d, size: cls.getRandom()};
// });
this.setup();
this.buildSVG();
this.populate();
}
);
}
// data = [{'number':1},{'number':2}];
private svg; // SVG in which we will print our chart
private margin: { // Space between the svg borders and the actual chart graphic
top: number,
right: number,
bottom: number,
left: number
};
private width: number; // Component width
private height: number; // Component height
private fillScale; // D3 scale for text color
tempData = [];
private getRandom() {
let cls = this;
let size = 10 + Math.random() * 100;
if(size > 70 && this.tempData.length <= 10) {
this.tempData.push(size);
}
if(this.tempData.length > 10 && size > 14) {
return 12;
}
return size;
}
private setup() {
this.margin = {
top : 10,
right : 10,
bottom: 10,
left : 10
};
this.width = 1200;
this.height = 450;
let minFontSize: number = 18 ;
let maxFontSize: number = 96 ;
this.fillScale = D3.scaleOrdinal(D3.schemeCategory10);
// this.fillScale = ['#abaaea','#abaaea','#abaaea','#abaaea','#abaaea'];
}
private buildSVG() {
this.svg = D3.select("#wordCloud")
.append('svg')
.attr('width', this.width + this.margin.left + this.margin.right)
.attr('height', this.height + this.margin.top + this.margin.bottom)
.append('g')
.attr('transform', 'translate(' + ~~(this.width / 2) + ',' + ~~(this.height / 2) + ')');
}
private populate() {
let fontFace: string = 'Roboto';
let fontWeight: string = 'normal';
let spiralType: string = 'archimedean';
d3.layout.cloud()
.size([this.width, this.height])
.words(this.data)
.padding(0)
.rotate(() => (~~(Math.random() * 2) * 0))
.font(fontFace)
.fontWeight(fontWeight)
.fontSize(d => (d.size))
.spiral(spiralType)
.on('end', () => {
this.drawWordCloud(this.data);
})
.start();
}
private drawWordCloud(words) {
this.svg
.selectAll('text')
.data(words)
.enter()
.append('text')
.style('font-size', d => 20 + 'px')
.style('fill', this.fillScale)
.attr('text-anchor', 'middle')
.attr('transform', d => 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')')
.attr('class', 'word-cloud')
.text(d => {
return d.term;
});
}
}
MY HTML IS GIVEN BELOW:
<div class ="tag_cloud-wrap" id ="wordCloud" ></div>
MY CSS:
.tag_cloud-wrap {
clear: both;
margin: 40px;
text-align: center;
}
JSON DATA obtained throug api call is:
0
:
{term: "#NYIAS", score: "-Infinity", normalizedScore: 0, totalTermFreq: 2, totalDocFreq: 2, …}
1
:
{term: "TORQUE", score: 0, normalizedScore: 0, totalTermFreq: 1, totalDocFreq: 1, …}
2
:
{term: "RS", score: 0, normalizedScore: 0, totalTermFreq: 1, totalDocFreq: 1, …}
3
:
{term: "SPORTBACK", score: 0, normalizedScore: 0, totalTermFreq: 1, totalDocFreq: 1, …}
4
:
{term: "COLOR", score: 0, normalizedScore: 0, totalTermFreq: 1, totalDocFreq: 1, …}
I am assigning term as text to word cloud.
Thanks in advance.
Related
Here I created several classes for each sprite. Examples are DeviceOne and DeviceTwo. All went well when only creating and loading 1 sprite. However when I call DeviceTwo and reload dataVizExtension I always get the following error.
Uncaught TypeError: Cannot read properties of undefined (reading 'dbId')
This is the code for DeviceOne, basically class for DeviceTwo is same. The different only the sprite images.
export class DeviceOne {
constructor(viewer, dataVizExtn) {
this.viewer = viewer;
this.dataVizExtn = null;
this.DataVizCore = null;
this.viewableType = null;
this.viewableData = null;
this.baseURL = "http://localhost:3000/assets/images/sprite/";
this.sensorPositions = {
Dasloop: {
x: 10,
y: -3,
z: 20,
},
Warning: {
x: 0,
y: 10,
z: 3,
},
};
this.dasloops = [
"img_gps_dasloop_online.svg",
"img_gps_dasloop_online-1.svg",
"img_gps_dasloop_online-2.svg",
"img_gps_dasloop_online-3.svg",
];
this.warnings = ["ic_warning.svg", "ic_warning-2.svg"];
this.startAnim1 = 0;
this.startAnim2 = 0;
this.startAnim3 = 0;
this.infoChart = new InfoChart(this.viewer, this.options);
}
/**
* #return {ViewableData} resulting viable data that contains all viewables (icons)
*/
async onSpriteLoadedToScene() {
this.dataVizExtn = await this.viewer.loadExtension(
"Autodesk.DataVisualization"
);
const dataVizCore = Autodesk.DataVisualization.Core;
this.onSpriteHovering = this.onSpriteHovering.bind(this);
this.viewer.addEventListener(
dataVizCore.MOUSE_HOVERING,
this.onSpriteHovering
);
this.onSpriteClicked = this.onSpriteClicked.bind(this);
this.viewer.addEventListener(dataVizCore.MOUSE_CLICK, this.onSpriteClicked);
const viewableType = dataVizCore.ViewableType.SPRITE;
const spriteColor = new THREE.Color(0xffffff);
const highlightedColor = new THREE.Color(0xe0e0ff);
const spriteIconUrl = `${this.baseURL}${"img_gps_dasloop_online.svg"}`;
const dasloopStyles = new dataVizCore.ViewableStyle(
viewableType,
spriteColor,
spriteIconUrl,
highlightedColor,
`${this.baseURL}${this.dasloops[0]}`,
this.dasloops.map((dasloop) => `${this.baseURL}${dasloop}`)
);
const warningStyles = new dataVizCore.ViewableStyle(
viewableType,
spriteColor,
`${this.baseURL}${"ic_warning.svg"}`,
highlightedColor,
`${this.baseURL}${this.warnings[0]}`,
this.warnings.map((warning) => `${this.baseURL}${warning}`)
);
this.viewableData = new dataVizCore.ViewableData();
this.viewableData.spriteSize = 30;
const simulationData = [
{ position: { x: 0, y: 0, z: 10 } },
{ position: { x: 5, y: -3, z: 10 } },
];
const warningData = [{ position: { x: 0, y: 0, z: 0 } }];
simulationData.forEach((myData, index) => {
const dbId = 10 + index;
const position = myData.position;
const viewable = new dataVizCore.SpriteViewable(
position,
dasloopStyles,
dbId
);
this.viewableData.addViewable(viewable);
});
warningData.forEach((myData, index) => {
const dbId = 15 + index;
const position = myData.position;
const viewableWarning = new dataVizCore.SpriteViewable(
position,
warningStyles,
dbId
);
this.viewableData.addViewable(viewableWarning);
});
await this.viewableData.finish();
this.dataVizExtn.addViewables(this.viewableData);
this.spriteToUpdate = this.dataVizExtn.viewableData.viewables.map(
(sprite) => sprite.dbId
);
this.animate = setInterval(this.getAnimateSprite.bind(this), 500);
}
getAnimateSprite() {
this.dataVizExtn.invalidateViewables(this.spriteToUpdate, (viewable) => {
switch (viewable.dbId) {
case 10:
return {
url: `${this.baseURL}${
this.dasloops[this.startAnim1++ % this.dasloops.length]
}`,
};
case 15:
return {
url: `${this.baseURL}${
this.warnings[this.startAnim2++ % this.warnings.length]
}`,
};
case 11:
return {
url: `${this.baseURL}${
this.dasloops[this.startAnim3++ % this.dasloops.length]
}`,
};
default:
break;
}
});
}
Sorry, it's a little hard for me to tell where the error came from with the above code snippet, but you mentioned reload dataVizExtension. So, I would advise you to check your this.animate = setInterval(this.getAnimateSprite.bind(this), 500);.
Did you clear the setInterval call by clearInterval(this.animate) while unloading and before reloading your extension?
I am trying to import a custom plugin into my chart.
Got this plugin from my previous question: Question
Its a plugin so that I can use Grace in my version of Chart.js.
The version of Chart.js I am using is V2.9.4.
I am using vue-chartjs in Nuxt!.
Couldn't really find an answer anywhere else.
This is how it looks now
This is how I want it to look
Thanks in advance. :)
I made a Component called 'BarChart' in my Components folder.
I made a normal .vue file in my pages directory. In the <template> tag I added my <Barchart/> component.
In that same .vue file I added a script in the <script> tag.
The plugin code is included in the codes below, I didn't include it anywhere yet.
Barchart.vue (Component)
<script>
import {Bar} from "vue-chartjs";
export default {
extends: Bar,
props: {
data: {
type: String,
default: () => {},
},
options: {
type: Object,
default: () => {},
},
},
computed: {
Chart() {
return['data', 'options'];
},
},
mounted() {
this.renderChart(this.data, this.options);
},
};
</script>
.vue file (Include component)
<div class="chart">
<BarChart :data="barChartData" :options="barChartOptions" :height="200"/>
</div>
.vue file (script tags)
<script>
import BarChart from "~/components/plugins/BarChart";
export default {
components: {
BarChart,
},
data() {
return {
barChartData: {
labels: ["Verzonden", "Ontvangen", "Geopend", "Kliks"],
datasets: [
{
data: [25, 20, 20, 18],
backgroundColor: [
'#7782FF',
'#403DD3',
'#FFB930',
'#00E437',
],
barThickness : 50,
},
],
},
barChartOptions: {
responsive: true,
legend: {
display: false,
},
scales: {
xAxes: [
{
gridLines: {
display: false,
},
ticks: {
fontColor: "black",
fontSize: 14,
},
},
],
yAxes: [
{
ticks: {
beginAtZero: true,
min: 0,
stepSize: 5,
fontColor: '#ABACB3',
},
gridLines: {
display: true,
borderDash: [4, 4],
color: '#EEEDFB',
drawBorder: false,
},
},
],
},
},
};
},
};
</script>
Plugin code (where do I put this and how do I make it work?)
const plugin = {
id: "customScale",
beforeLayout: (chart, options, c) => {
let max = Number.MIN_VALUE;
let min = Number.MAX_VALUE
let grace = options.grace || 0
chart.data.datasets.forEach((dataset) => {
max = Math.max(max, Math.max(...dataset.data));
min = Math.min(min, Math.min(...dataset.data))
})
if (typeof grace === 'string' && grace.includes('%')) {
grace = Number(grace.replace('%', '')) / 100
chart.options.scales.yAxes[0].ticks.suggestedMax = max + (max * grace)
chart.options.scales.yAxes[0].ticks.suggestedMin = min - (min * grace)
} else if (typeof grace === 'number') {
chart.options.scales.yAxes[0].ticks.suggestedMax = max + grace
chart.options.scales.yAxes[0].ticks.suggestedMin = min - grace
}
}
}
According to the vue-chartjs documentation you can do this in 2 ways.
If you want the plugin to be available for all your charts you can use the global registration like so:
import Chart from 'chart.js'
Chart.pluginService.register({
id: "customScale",
beforeLayout: (chart, options, c) => {
let max = Number.MIN_VALUE;
let min = Number.MAX_VALUE
let grace = options.grace || 0
chart.data.datasets.forEach((dataset) => {
max = Math.max(max, Math.max(...dataset.data));
min = Math.min(min, Math.min(...dataset.data))
})
if (typeof grace === 'string' && grace.includes('%')) {
grace = Number(grace.replace('%', '')) / 100
chart.options.scales.yAxes[0].ticks.suggestedMax = max + (max * grace)
chart.options.scales.yAxes[0].ticks.suggestedMin = min - (min * grace)
} else if (typeof grace === 'number') {
chart.options.scales.yAxes[0].ticks.suggestedMax = max + grace
chart.options.scales.yAxes[0].ticks.suggestedMin = min - grace
}
}
});
This way of importing and registering should work from anywhere in your app.
The second way is an inline plugin. This needs to be done in your BarChart.vue and goes like this:
mounted() {
this.addPlugin(
Chart.pluginService.register({
id: "customScale",
beforeLayout: (chart, options, c) => {
let max = Number.MIN_VALUE;
let min = Number.MAX_VALUE
let grace = options.grace || 0
chart.data.datasets.forEach((dataset) => {
max = Math.max(max, Math.max(...dataset.data));
min = Math.min(min, Math.min(...dataset.data))
})
if (typeof grace === 'string' && grace.includes('%')) {
grace = Number(grace.replace('%', '')) / 100
chart.options.scales.yAxes[0].ticks.suggestedMax = max + (max * grace)
chart.options.scales.yAxes[0].ticks.suggestedMin = min - (min * grace)
} else if (typeof grace === 'number') {
chart.options.scales.yAxes[0].ticks.suggestedMax = max + grace
chart.options.scales.yAxes[0].ticks.suggestedMin = min - grace
}
}
});
)
}
Currently we are trying to input uber data that includes time of day and ride fare into our TensorFlow.js model. We noticed that when we ran the model on the browser, the points are showing up on our scatterplot but during the training the loss and mean squared error values are not showing up and most importantly our model is not displaying a prediction line.
var userData = [
{
"City": "San Francisco",
"Product_Type": "UberEATS Marketplace",
"Trip_or_Order_Status": "COMPLETED",
"Request_Time": "2019-06-16 04:10:44 +0000 UTC",
"Begin_Trip_Time": "2019-06-16 04:44:40 +0000 UTC",
"Begin_Trip_Lat": "37.7352602",
"Begin_Trip_Lng": "-122.4203465",
"Begin_Trip_Address": "",
"Dropoff_Time": "2019-06-16 04:44:40 +0000 UTC",
"Dropoff_Lat": "37.7352602",
"Dropoff_Lng": "-122.4203465",
"Dropoff_Address": "",
"Distance_miles": "2.04",
"Fare_Amount": "32.34",
"Fare_Currency": "USD"
}...]
async function getData() {
const carsData = await userData;
// Here we map out the values for each car and filter out the list item that do not have an day or a pay value
const cleaned = carsData.map(car => ({
timeInMinutes: calculateMins(car.Request_Time),
pay_rate: normalizeUberPrice(car.Distance_miles, car.Fare_Amount),
}))
.filter(car => (car.day != null && car.pay != null));
return cleaned;
}
async function run() {
const data = await getData();
const values = data.map(d => ({
x: d.day,
y: d.pay,
}));
tfvis.render.scatterplot(
{ name: 'Horsepower v MPG' },
{ values },
{
xAxisDomain: [0, 1600],
yAxisDomain: [0,10],
xLabel: 'Day',
yLabel: 'Pay',
height: 300
}
);
const model = createModel();
tfvis.show.modelSummary({ name: 'Model Summary' }, model);
// Convert the data to a form we can use for training.
const tensorData = convertToTensor(data);
console.log(tensorData)
const { inputs, labels } = tensorData;
// Train the model
await trainModel(model, inputs, labels);
console.log('Done Training');
testModel(model, data, tensorData);
}
function createModel() {
const model = tf.sequential();
model.add(tf.layers.dense({ inputShape: [1], units: 25, useBias: true }));
model.add(tf.layers.dense({ units: 50, activation: "sigmoid" }));
model.add(tf.layers.dense({ units: 1, useBias: true }));
return model;
}
function convertToTensor(data) {
return tf.tidy(() => {
tf.util.shuffle(data);
const inputs = data.map(d => d.pay)
const labels = data.map(d => d.day);
const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);
const labelTensor = tf.tensor2d(labels, [labels.length, 1]);
//Step 3. Normalize the data to the range 0 - 1 using min-max scaling
const inputMax = inputTensor.max();
const inputMin = inputTensor.min();
const labelMax = labelTensor.max();
const labelMin = labelTensor.min();
const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));
const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));
return {
inputs: normalizedInputs,
labels: normalizedLabels,
// Return the min/max bounds so we can use them later.
inputMax,
inputMin,
labelMax,
labelMin,
}
});
}
async function trainModel(model, inputs, labels) {
model.compile({
optimizer: tf.train.adam(),
loss: tf.losses.meanSquaredError,
metrics: ['mse'],
});
const batchSize = 32;
const epochs = 30;
callbacks: tfvis.show.fitCallbacks(
{ name: 'Training Performance' },
['loss', 'mse'],
{
xAxisDomain: [0, 100],
yAxisDomain: [0,1],
height: 200,
callbacks: ['onEpochEnd'] }
// ',onBatchEnd'
),
history: tfvis.show.history({
name: 'History'},
history,
["loss","mse"])
});
}
function testModel(model, inputData, normalizationData) {
const { inputMax, inputMin, labelMin, labelMax } = normalizationData;
const [xs, preds] = tf.tidy(() => {
const xs = tf.linspace(0, 1, 100);
const preds = model.predict(xs.reshape([100, 1]));
const unNormXs = xs
.mul(inputMax.sub(inputMin))
.add(inputMin);
const unNormPreds = preds
.mul(labelMax.sub(labelMin))
.add(labelMin);
return [unNormXs.dataSync(), unNormPreds.dataSync()];
});
const predictedPoints = Array.from(xs).map((val, i) => {
return { x: val, y: preds[i] }
});
const originalPoints = inputData.map(d => ({
x: d.pay, y: d.day,
}));
console.log("ORIGINAL POINTS:")
console.log(originalPoints)
tfvis.render.scatterplot(
{ name: 'Model Predictions vs Original Data' },
{ values: [originalPoints, predictedPoints], series: ['original', 'predicted'] },
{
xAxisDomain: [0,10],
yAxisDomain: [0,1600],
xLabel: 'Horsepower',
yLabel: 'MPG',
height: 1000
}
);
}
document.addEventListener('DOMContentLoaded', run);
Basically we want to see a predicted line for our data but were not getting anything back.
It worked when we used data like this:
var userData = [{
day: 1
pay: 20
},...]
The data processing is not well performed. Thus, the values used for prediction contain NaN and Infinity. As a result, the error computed by model.fit is NaN and could therefore not be displayed on the chart of tfjs-vis.
The filtering
.filter(car => (car.day != null && car.pay != null));
is not removing NaN and Infinity. Instead, this condition can be used:
.filter(car => isFinite(car.pay + car.day) && !isNaN(car.pay + car.day));
Though, the NaN and Infinity are found within the values of car.day, here a general filtering is made over car.pay and car.day - thus the additional operation - to make sure that these values will not appear anywhere in the cleaned data.
here you can see how to display the loss.
Class Variable Name: addPointY
"addPointY" Using Function:
setInterval(function () {
var y = Math.round(Math.random() * 100);
series.addPoint(this.addPointY, true, true);
}, 3000);
I have to find a way to use it.
This is a customer requirement and has not been resolved.
Please tell me another way.
The class variable must be used in any of its methods.
But I could not get the class variable.
Do not you have a smart developer who solved the same problem?
#Injectable()
export class HighChartService implements ChartService {
private addPointY: number = 0;
shiftAddPoint(data: number) {
this.addPointY = data;
console.log(this.addPointY);
}
/**
* #see DynamicChart start function
* #param obj chart Object
* #param title Top Title
* #param type ChartType
* #param yAxisTitle Left Title
* #param series Chart data
* #author jskang
* #since 2017/10/12
*/
dynamicInitOptions(title: string, type: string, yAxisTitle: string, series: Object[]) {
if (!type) { type = "line"; }
let obj = new Chart({
chart: {
type: type,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var y = Math.round(Math.random() * 100);
series.addPoint(this.addPointY, true, true);
}, 3000);
}
}
},
title: { text: title },
xAxis: {
categories: [0,1,2,3,4,5,6],
labels: {
formatter: function () {
let xAxis = "";
if(this.value % 7 == 0){ xAxis = "일"; }
else if(this.value % 7 == 1){ xAxis = "월"; }
else if(this.value % 7 == 2){ xAxis = "화"; }
else if(this.value % 7 == 3){ xAxis = "수"; }
else if(this.value % 7 == 4){ xAxis = "목"; }
else if(this.value % 7 == 5){ xAxis = "금"; }
else if(this.value % 7 == 6){ xAxis = "토"; }
return xAxis;
}
}
},
yAxis: {
title: {
text: yAxisTitle
},
labels: {
formatter: function () {
return this.value;
}
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
series: series
});
return obj;
}
}
The this inside your callback function for setInterval does not point to the current class instance because when you use function () {} syntax it creates its own binding for this based on how it is called.
To fix this use arrow functions which preserves the context and you can access your class properties inside the callback:
load: () => { // Notice arrow function here
// set up the updating of the chart each second
var series = this.series[0];
setInterval(() => { // Notice arrow function here
var y = Math.round(Math.random() * 100);
series.addPoint(this.addPointY, true, true);
}, 3000);
}
Another way you can solve this is by using the that pattern where you capture your this where it points to your class instance and use it wherever you need to refer to your instance:
dynamicInitOptions(title: string, type: string, yAxisTitle: string, series: Object[]) {
if (!type) { type = "line"; }
let that = this; // Capture `this` here
let obj = new Chart({
chart: {
type: type,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var y = Math.round(Math.random() * 100);
series.addPoint(that.addPointY, true, true); // Use `that` instead of `this here
}, 3000);
}
}
}
// ...
});
}
I have the following JQGrid table, which is being generated from JSON data. I want to be able to generate/export or create a pdf file based on the table data state that is view able. I am using JSON , Jqgrid and Javascript
How do I generate a pdf file from the data ?
Here My FIDDLE
JS CODE
$(document).ready(function() {
var jsonData = {
"Name": "Julie Brown",
"Account": "C0010",
"LoanApproved": "12/5/2015",
"LastActivity": "4/1/2016",
"PledgedPortfolio": "4012214.00875",
"MaxApprovedLoanAmt": "2050877.824375",
"LoanBalance": "1849000",
"AvailableCredit": "201877.824375",
"Aging": "3",
"Brokerage": "My Broker",
"Contact": "Robert L. Johnson",
"ContactPhone": "(212) 902-3614",
"RiskCategory": "Yellow",
"rows": [{
"ClientID": "C0010",
"Symbol": "WEC",
"Description": "Western Electric Co",
"ShareQuantity": "20638",
"SharePrice": "21.12",
"TotalValue": "435874.56",
"LTVCategory": "Equities",
"LTVRatio": "50%",
"MaxLoanAmt": "217937.28"
}, {
"ClientID": "C0010",
"Symbol": "BBB",
"Description": "Bins Breakers and Boxes",
"ShareQuantity": "9623",
"SharePrice": "74.29125",
"TotalValue": "714904.69875",
"LTVCategory": "Equities",
"LTVRatio": "50%",
"MaxLoanAmt": "357452.349375"
}, {
"ClientID": "C0010",
"Symbol": "GPSC",
"Description": "Great Plains Small Cap Stock",
"ShareQuantity": "49612",
"SharePrice": "14.24",
"TotalValue": "706474.88",
"LTVCategory": "Mutual Funds - Small Cap",
"LTVRatio": "40%",
"MaxLoanAmt": "282589.952"
}]
},
mmddyyyy = "";
/*********************************************************************/
$("#output").jqGrid({
url: "/echo/json/",
mtype: "POST",
datatype: "json",
postData: {
json: JSON.stringify(jsonData)
},
colModel: [
/** { name: 'ClientID', label:'ClientID',width: 80, key: true },****/
{
name: 'Symbol',
width: 65
}, {
name: 'Description',
width: 165
}, {
name: 'ShareQuantity',
align: 'right',
width: 85,
classes: "hidden-xs", labelClasses: "hidden-xs",
formatter: 'currency',
formatoptions: {
prefix: " ",
suffix: " "
}
}, {
name: 'SharePrice',
label: 'Share Price',
align: 'right',
width: 100,
classes: "hidden-xs", labelClasses: "hidden-xs",
template: "number",
formatoptions: {
prefix: " $",
decimalPlaces: 4
}
},
/*{ label: 'Value1',
name: 'Value1',
width: 80,
sorttype: 'number',
formatter: 'number',
align: 'right'
}, */
{
name: 'TotalValue',
label: 'Total Value',
width: 160,
sorttype: 'number',
align: "right",
search: false,
formatter: 'currency',
formatoptions: {
prefix: " $",
suffix: " "
}
}, {
name: 'LTVRatio',
label: 'LTV Ratio',
width: 70,
sorttype: 'number',
align: "right",
formatter: 'percentage',
formatoptions: {
prefix: " ",
suffix: " "
}
}, {
name: 'LTVCategory',
label: 'LTV Category',
classes: "hidden-xs", labelClasses: "hidden-xs",
width: 120,
width: 165
},
{
name: 'MaxLoanAmt',
label: 'MaxLoanAmount',
width: 165,
sorttype: 'number',
align: "right",
search: false,
formatter: 'currency',
formatoptions: {
prefix: " $",
suffix: " "
}
}
],
additionalProperties: ["Symbol", "Description"],
subGrid: true,
subGridRowExpanded: function (subgridDivId, rowid) {
var item = $(this).jqGrid("getLocalRow", rowid);
$("#" + $.jgrid.jqID(subgridDivId)).html("Symbol: <em>" + item.Symbol +
"</em><br/>Description: <em>" + item.Description + "</em>");
},
beforeProcessing: function (data) {
var symbolsMap = {}, symbolsValues = ":All", rows = data.rows, i, symbol;
for (i = 0; i < rows.length; i++) {
symbol = rows[i].Symbol;
if (!symbolsMap.hasOwnProperty(symbol)) {
symbolsMap[symbol] = 1;
symbolsValues += ";" + symbol + ":" + symbol;
}
}
$(this).jqGrid("setColProp", 'Symbol', {
stype: "select",
searchoptions: {
value: symbolsValues
}
}).jqGrid('destroyFilterToolbar')
.jqGrid('filterToolbar', {
stringResult: true,
searchOnEnter: false,
defaultSearch : "cn"
});
},
/*beforeProcessing: function (data) {
var item, i, n = data.length;
for (i = 0; i < n; i++) {
item = data[i];
item.Quantity = parseFloat($.trim(item.Quantity).replace(",", ""));
item.LTVRatio = parseFloat($.trim(item.LTVRatio *10000).replace(",", ""));
item.Value = parseFloat($.trim(item.Value).replace(",", ""));
item.Num1 = parseInt($.trim(item.Num1).replace(",", ""), 10);
item.Num2 = parseInt($.trim(item.Num2).replace(",", ""), 10);
}
}, */
iconSet: "fontAwesome",
loadonce: true,
rownumbers: true,
cmTemplate: {
autoResizable: true,
editable: true
},
autoResizing: {
compact: true
},
autowidth: true,
height: 'auto',
forceClientSorting: true,
sortname: "Symbol",
footerrow: true,
caption: "<b>Collateral Value</b> <span class='pull-right' style='margin-right:20px;'>Valuation as of: " + mmddyyyy + "</span>",
loadComplete: function() {
var $self = $(this),
sum = $self.jqGrid("getCol", "Price", false, "sum"),
sum1 = $self.jqGrid("getCol", "MaxLoanAmt", false, "sum");
//ltvratio = $self.jqGrid("getCol","LTVRatio:addas", "Aved Loan Amount");
$self.jqGrid("footerData", "set", {
LTVCategory: "Max Approved Loan Amount:",
Price: sum,
MaxLoanAmt: sum1
});
}
});
$("#output").jqGrid('filterToolbar', {stringResult: true, searchOnEnter: false, defaultSearch : "cn"});
$(window).on("resize", function () {
var newWidth = $("#output").closest(".ui-jqgrid").parent().width();
$("#output").jqGrid("setGridWidth", newWidth, true);
}).triggerHandle("resize");
});
There is no build in method to export jqgrid data to pdf. You have to use third party tools( I personally like iTextSharp which can be downloaded from Here . You have to create action method for printing the grid data in your controller.
Here is also another one example one guy made.
Here is also another example in trirand. If you see the source code they are using iTextHsarp.
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using JQGridMVCExamples.Models;
using Trirand.Web.Mvc;
using System.IO;
//
// For PDF export we are using the free open-source iTextSharp library.
//
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.Data;
namespace JQGridMVCExamples.Controllers.Grid
{
public partial class GridController : Controller
{
// This is the default action for the View. Use it to setup your grid Model.
public ActionResult ExportPDF()
{
// Get the model (setup) of the grid defined in the /Models folder.
var gridModel = new OrdersJqGridModel();
var ordersGrid = gridModel.OrdersGrid;
// Setting the DataUrl to an action (method) in the controller is required.
// This action will return the data needed by the grid
ordersGrid.DataUrl = Url.Action("PDFGrid_DataRequested");
// customize the default Orders grid model with custom settings
// NOTE: you need to call this method in the action that fetches the data as well,
// so that the models match
SetPDFExportGrid(ordersGrid);
// Pass the custmomized grid model to the View
return View(gridModel);
}
// This method is called when the grid requests data
public JsonResult PDFGrid_DataRequested()
{
// Get both the grid Model and the data Model
// The data model in our case is an autogenerated linq2sql database based on Northwind.
var gridModel = new OrdersJqGridModel();
var northWindModel = new NorthwindDataContext();
// customize the default Orders grid model with our custom settings
SetPDFExportGrid(gridModel.OrdersGrid);
// Save the current grid state in Session
// We will later need it for PDF Export
JQGridState gridState = gridModel.OrdersGrid.GetState();
Session["gridState"] = gridState;
// return the result of the DataBind method, passing the datasource as a parameter
// jqGrid for ASP.NET MVC automatically takes care of paging, sorting, filtering/searching, etc
return gridModel.OrdersGrid.DataBind(northWindModel.Orders);
}
public JsonResult PDFExport_AutoCompleteShipName(string term)
{
var northWindModel = new NorthwindDataContext();
JQAutoComplete autoComplete = new JQAutoComplete();
autoComplete.DataField = "ShipName";
autoComplete.AutoCompleteMode = AutoCompleteMode.BeginsWith;
autoComplete.DataSource = from o in northWindModel.Orders
select o;
return autoComplete.DataBind();
}
private void SetPDFExportGrid(JQGrid ordersGrid)
{
// show the search toolbar
ordersGrid.ToolBarSettings.ShowSearchToolBar = true;
ordersGrid.ToolBarSettings.ShowSearchButton = true;
var orderDateColumn = ordersGrid.Columns.Find(c => c.DataField == "OrderDate");
orderDateColumn.DataFormatString = "{0:yyyy/MM/dd}";
orderDateColumn.SearchType = SearchType.DatePicker;
orderDateColumn.DataType = typeof(DateTime);
orderDateColumn.SearchControlID = "DatePicker";
orderDateColumn.SearchToolBarOperation = SearchOperation.IsEqualTo;
var shipNameColumn = ordersGrid.Columns.Find(c => c.DataField == "ShipName");
shipNameColumn.SearchType = SearchType.AutoComplete;
shipNameColumn.DataType = typeof(string);
shipNameColumn.SearchControlID = "AutoComplete";
shipNameColumn.SearchToolBarOperation = SearchOperation.Contains;
var orderIDColumns = ordersGrid.Columns.Find(c => c.DataField == "OrderID");
orderIDColumns.Searchable = true;
orderIDColumns.DataType = typeof(int);
orderIDColumns.SearchToolBarOperation = SearchOperation.IsEqualTo;
SetPDFCustomerIDSearchDropDown(ordersGrid);
SetPDFFreightSearchDropDown(ordersGrid);
}
private void SetPDFCustomerIDSearchDropDown(JQGrid ordersGrid)
{
// setup the grid search criteria for the columns
JQGridColumn customersColumn = ordersGrid.Columns.Find(c => c.DataField == "CustomerID");
customersColumn.Searchable = true;
// DataType must be set in order to use searching
customersColumn.DataType = typeof(string);
customersColumn.SearchToolBarOperation = SearchOperation.IsEqualTo;
customersColumn.SearchType = SearchType.DropDown;
// Populate the search dropdown only on initial request, in order to optimize performance
if (ordersGrid.AjaxCallBackMode == AjaxCallBackMode.RequestData)
{
var northWindModel = new NorthwindDataContext();
var searchList = from customers in northWindModel.Customers
select new SelectListItem
{
Text = customers.CustomerID,
Value = customers.CustomerID
};
customersColumn.SearchList = searchList.ToList<SelectListItem>();
customersColumn.SearchList.Insert(0, new SelectListItem { Text = "All", Value = "" });
}
}
private void SetPDFFreightSearchDropDown(JQGrid ordersGrid)
{
// setup the grid search criteria for the columns
JQGridColumn freightColumn = ordersGrid.Columns.Find(c => c.DataField == "Freight");
freightColumn.Searchable = true;
// DataType must be set in order to use searching
freightColumn.DataType = typeof(decimal);
freightColumn.SearchToolBarOperation = SearchOperation.IsGreaterOrEqualTo;
freightColumn.SearchType = SearchType.DropDown;
// Populate the search dropdown only on initial request, in order to optimize performance
if (ordersGrid.AjaxCallBackMode == AjaxCallBackMode.RequestData)
{
List<SelectListItem> searchList = new List<SelectListItem>();
searchList.Add(new SelectListItem { Text = "> 10", Value = "10" });
searchList.Add(new SelectListItem { Text = "> 30", Value = "30" });
searchList.Add(new SelectListItem { Text = "> 50", Value = "50" });
searchList.Add(new SelectListItem { Text = "> 100", Value = "100" });
freightColumn.SearchList = searchList.ToList<SelectListItem>();
freightColumn.SearchList.Insert(0, new SelectListItem { Text = "All", Value = "" });
}
}
public ActionResult ExportToPDF(string exportType)
{
var gridModel = new OrdersJqGridModel();
var northWindModel = new NorthwindDataContext();
var grid = gridModel.OrdersGrid;
// Get the last grid state the we saved before in Session in the DataRequested action
JQGridState gridState = Session["GridState"] as JQGridState;
// Need to set grid options again
SetExportGrid(grid);
if (String.IsNullOrEmpty(exportType))
exportType = "1";
DataTable exportData;
switch (exportType)
{
case "1":
grid.ExportSettings.ExportDataRange = ExportDataRange.All;
exportData = grid.GetExportData(northWindModel.Orders);
ExportToPDF(exportData);
break;
case "2":
grid.ExportSettings.ExportDataRange = ExportDataRange.Filtered;
exportData = grid.GetExportData(northWindModel.Orders, gridState);
ExportToPDF(exportData);
break;
case "3":
grid.ExportSettings.ExportDataRange = ExportDataRange.FilteredAndPaged;
exportData = grid.GetExportData(northWindModel.Orders, gridState);
ExportToPDF(exportData);
break;
}
return View();
}
private void ExportToPDF(DataTable dt)
{
//
// For PDF export we are using the free open-source iTextSharp library.
//
Document pdfDoc = new Document();
MemoryStream pdfStream = new MemoryStream();
PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, pdfStream);
pdfDoc.Open();//Open Document to write
pdfDoc.NewPage();
Font font8 = FontFactory.GetFont("ARIAL", 7);
PdfPTable PdfTable = new PdfPTable(dt.Columns.Count);
PdfPCell PdfPCell = null;
//Add Header of the pdf table
for (int column = 0; column < dt.Columns.Count; column++)
{
PdfPCell = new PdfPCell(new Phrase(new Chunk(dt.Columns[column].Caption, font8)));
PdfTable.AddCell(PdfPCell);
}
//How add the data from datatable to pdf table
for (int rows = 0; rows < dt.Rows.Count; rows++)
{
for (int column = 0; column < dt.Columns.Count; column++)
{
PdfPCell = new PdfPCell(new Phrase(new Chunk(dt.Rows[rows][column].ToString(), font8)));
PdfTable.AddCell(PdfPCell);
}
}
PdfTable.SpacingBefore = 15f; // Give some space after the text or it may overlap the table
pdfDoc.Add(PdfTable); // add pdf table to the document
pdfDoc.Close();
pdfWriter.Close();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=gridexport.pdf");
Response.BinaryWrite(pdfStream.ToArray());
Response.End();
}
}
}