right align dynamic column of datatype number in iggrid - infragistics

I am using Ignite UI grid.
The columns is dynamically build from the database like this:-
$.post('/Main/GetColumns',function(data){
$("#mygrid").igGrid({
columns: data,
width: "100%",
height: "100%",
})
});
The problem is that i dont know which of the column will be of datatype number since data is comming from database for columns and i have to right align the numeric columns.
The only code i have found is
args.owner.element.find("tr td:nth-child(3)").css("text-align", "right");
to set 3rd column as right align.
Since i dont know the column order, i am only left to check for datatype and right align the column,
Is there any way to align column on basis of datatype or any other method to do this?

The data type if the column is used for it's representation(formatting) and editing behavior, but there's no extra markup generated that you can use to target with styling.
However, you are building column definitions server side, where you know exactly what type each column is while creating its definition, no?
Update: It's been a while since the original answer and for future reference you can use the columnCssClass to apply your class to the actual TD rather than the template. The latter is still a valid option for advanced tinkering.
Easiest way I can think of is through Column templates - this way you can add whatever styling / formatting to the columns. For example, based of whatever logic you need, you return some columns as:
{
key: 'status',
dataType: 'bool',
headerText: 'Status',
template: '<div class="rightAlign"> ${status} </div>'
}
You apply "text-align:right;" though the class and skip adding template for columns that should be with default look. Since this definition is generated on the server (imagine my example uses Node.js :P ) you can have those templates static, or create them differently each time - it's up to you.
JSFiddle: http://jsfiddle.net/damyanpetev/wsZ8c/
Note: Make sure you use a block (div,p) in this case as you need something that will take up the entire grid cell in order to align text inside.
If that solution doesn't fit, you will have to go through columns and apply styling on the client in a similar way you were thinking of.

Here is how I dynamically align the text in the columns in the infragistics igHierarchicalGrid according to their data types:
$("#grid1").on("iggriddatarendered", function (event, args) {
var columns = $("#grid1").igHierarchicalGrid("option", "columns");
//var RDate = $("#grid1").igHierarchicalGrid("getCellValue", 1, 1);
var columnIndex = 0;
var trtd = 2;
for (var idx = 0; idx < columns.length; idx++) {
if (columns[idx].dataType == "number" || columns[idx].dataType == "double")
args.owner.element.find("tr td:nth-child(" + trtd + ")").css("text-align", "right");
if (columns[idx].dataType == "string" || columns[idx].dataType == "date")
args.owner.element.find("tr td:nth-child(" + trtd + ")").css("text-align", "left");
columnIndex++;
trtd = columnIndex + 2;
}
});
As you see I am starting with vartd = 2 and this is because there are 2 elements in the table
(I use hierachcical grid) before the columns in the grid are available. You must debug and investigate if in your case
the columns of the grid are coming after the second DOM element or after the first.

In easy way you can add css into columnCssClass property and applied into grid where you were define column information
Style:
<style>
.right-align {
text-align: right;
}
.left-align {
text-align: left;
}
.center-align {
text-align: center;
}
</style>
and grid code snippet:
{ headerText: 'Option', key: "Option", dataType: "string", width: "10%", hidden: true },
{ headerText: 'ID', key: "Program_Id", dataType: "string", width: "10%", columnCssClass: "right-align" },
{ headerText: 'Desc', key: "Program_Des", dataType: "string", width: "10%", columnCssClass: "left-align" },
{ headerText: 'Status', key: "program_Status", dataType: "Bool", width: "10%", columnCssClass: "center-align" },

Related

ChartJS 4 migration: access other datasets from tooltip callback

I'm migrating from ChartJS 2.9.3 to 4.2.1 (current). By following the 3.x and 4.x migration guides, I've sorted most things out, but I've come across a problem that I don't see a solution for.
One of my charts is a stacked bar chart. There are two datasets for it:
let chartData = {
// other stuff...
datasets: [
{ label: "Has thing", data: [200, 250, etc] },
{ label: "Does not has thing", data: [10, 4, etc] },
]
}
In my tooltips, I was accessing both datasets to create a custom tooltip with the percent representation of each part of each stack. For instance, the tooltips for the first stack might say: "Has thing: 200 (95.2%)" and "Does not has thing: 10 (4.8%)". My callback function looked like this:
// other stuff
callbacks: {
label: function(tooltipItem, data) {
let dataset = data.datasets[tooltipItem.datasetIndex];
let count_with = data.datasets[0].data[tooltipItem.index]
let count_without = data.datasets[1].data[tooltipItem.index]
let total = count_with + count_without
let this_dataset_count = dataset.data[tooltipItem.index]
let this_dataset_perc = (this_dataset_count / total * 100).toFixed(1)
let label = dataset.label + ": "
label += this_dataset_count + " (" + this_dataset_perc + "%)"
return label;
}
}
Looking at the 3.x migration guide, it appears they removed the data parameter from the tooltip callback, opting instead to add the item's dataset directly to the tooltipItem. Unfortunately, they don't seem to specify how I can access other datasets.
Has this functionality simply been removed completely, or is there a different way to access it?
As #kikon pointed out, data is accessible via context.chart.data. For some reason, that doesn't show up for me when I console.dir() the context object so I was just completely overlooking it.
Anyway, for anyone this might help in the future, here's the working version:
callbacks: {
label: function(context) {
const datasets = context.chart.data.datasets
const countWith = datasets[0].data[context.dataIndex]
const countWithout = datasets[1].data[context.dataIndex]
const perc = (context.raw / (countWith + countWithout) * 100).toFixed(1)
return `${context.dataset.label}: ${context.formattedValue} (${perc}%)`
}
}

ChartJS Tooltip - Change Data Format Displayed

I've created a horizontal floating bar chart using ChartJS. The data I am passing in is formatted as:
[
{
rowName: 'Project 1',
startDate: '2021-03-15',
endDate: '2021-04-20',
}
]
Where my x axis shows a month/year and my y axis shows the rowName. I've added chartjs-adapater-date-fns but in order to get the floating bars to work, I've had to convert the startDate and endDate into new dates and then use the .getTime() function to retrieve a number for the data the chart expects. E.g. [new Date(startDate).getTime(), new Date(endDate).getTime()].
On my tooltip, it shows the label as rowName which is what I'm wanting, however the data value shows as the two number values being passed in.
I'm wanting to show the tooltip in the following format:
Project 1
Start Date: 05/03/2021
End Date: 20/04/2021
What is the best way of doing this?
Note: I have consoled the context and found that data.raw provides me with 2021-05-03,2021-04-20 if that is of any use?
Instead of new date pass your input date , Tooltip will show with formatted date value.
var barOption = {
tooltips: {
callbacks: {
label: function(t, d) {
this.date=new Date();
let formated_date = this.datepipe.transform(this.date, 'dd/MM/yyy');
return formated_date;
},
},
},
}

Obtain max value of y axis of line chart rendered with Chart.js

I use Chart.js to render a scattered line chart, which works pretty well.
For the rendering algorithm I need to find out the highest value shown on the y-axis, so let's say my "largest" point in the dataset has y = 248, so the y-axis shows 250 as the largest value. I need to find out that it's 250.
I tried to inspect the chart object at runtime, like so:
lineChart.options.scales[0].ticks.??
but it seems that I can only find out the settings I set myself programmatically.
Also looking at the comprehensive Chart.js docs did not point me to the solution.
Any advice how to figure out this value?
There is callback method in which you can get the array of values which will show on yAxes.
The first element of that array will be the highest value for the yAxes. Below is the sample code for the same.
var yAxesticks = [];
var highestVal;
var chartInstanceHoverModeNearest = new Chart(ctx, {
type: 'bar',
data: data,
options:{
scales: {
yAxes : [{
ticks : {
beginAtZero : true,
callback : function(value,index,values){
yAxesticks = values;
return value;
}
}
}]
}
}
});
highestVal = yAxesticks[0];

"Total rows" in custom Power BI visualizations

I have a question about creating the custom visualization in Power BI.
I want to implement a "total row" functionality which is available in the built-in matrix visualization. The main concept is to automatically sum-up every value and group it by the rows. This is how it's looks like on the matrix visualization:
But, to be honest, I don't know how to achieve this. I try different things but I can't receive this grouped values in the dataViews.
I tried to analyze the built-in matrix.ts code but it's quite different that the custom visualizations code. I found the customizeQuery method which set the subtotalType property to the rows and columns - I tried to add this in my code but I don't see any difference in the dataViews (I don't found the grouped value).
Currently my capabilities.dataViewMappings is set like this:
dataViewMappings: [
{
conditions: [
{ 'Rows': { max: 3 } }
],
matrix: {
rows: {
for: { in: 'Rows' },
},
values: {
for: { in: 'Values' }
},
},
}
]
Does anyone know how we could achieve this "total row" functionality?
UPDATE 1
I already found the solution: when we implement the customizeQuery method (in the same way as the customizeQuery method in the matrix.ts code), and then add the reference to it in the powerbi.visuals.plugins.[visualisationName+visualisationAddDateEpoch].customizeQuery then it works as expected (I receive in the dataViews[0].matrix.row.root children elements that has the total values from row).
The only problem now is that I don't know exactly how to add correctly this reference to the customizeQuery method. For example the [visualisationName+visualisationAddDateEpoch] is Custom1451458639997, and I don't know what those number will be (I know only the name). I created the code in my visualisation constructor as below (and it's working):
constructor() {
var targetCustomizeQuery = this.constructor.customizeQuery;
var name = this.constructor.name;
for(pluginName in powerbi.visuals.plugins) {
var patt = new RegExp(name + "[0-9]{13}");
if(patt.test(pluginName)) {
powerbi.visuals.plugins[pluginName].customizeQuery = targetCustomizeQuery;
break;
}
}
}
But in my opinion this code is very dirty and inelegant. I want to improve it - what is the correct way to tell the Power BI that we implement the custom customizeQuery method and it should use it?
UPDATE 2
Code from update 1 works only with the Power BI in the web browser (web based). On the Power BI Desktop the customizeQuery method isn't invoked. What is the correct way to tell the Power BI to use our custom customizeQuery method? In the code from PowerBI-visuals repository using PowerBIVisualPlayground we could declare it in the plugin.ts file (in the same way like the matrix visual is done):
export let matrix: IVisualPlugin = {
name: 'matrix',
watermarkKey: 'matrix',
capabilities: capabilities.matrix,
create: () => new Matrix(),
customizeQuery: Matrix.customizeQuery,
getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => Matrix.getSortableRoles(),
};
But, in my opinion, from the Power BI Dev Tools we don't have access to add additional things to this part of code. Any ideas?
It seems you're missing the columns mapping in your capabilities. Take a look at the matrix capabilities (also copied for reference below) and as a first step adopt that structure initially. The matrix calculates the intersection of rows and columns so without the columns in capabilities its doubtful you'll get what you want.
Secondly, in the matrix dataview passed to Update you'll get a 'DataViewMatrixNode' with isSubtotal: true Take a look at the unit tests for matrix to see the structure.
dataViewMappings: [{
conditions: [
{ 'Rows': { max: 0 }, 'Columns': { max: 0 }, 'Values': { min: 1 } },
{ 'Rows': { min: 1 }, 'Columns': { min: 0 }, 'Values': { min: 0 } },
{ 'Rows': { min: 0 }, 'Columns': { min: 1 }, 'Values': { min: 0 } }
],
matrix: {
rows: {
for: { in: 'Rows' },
/* Explicitly override the server data reduction to make it appropriate for matrix. */
dataReductionAlgorithm: { window: { count: 500 } }
},
columns: {
for: { in: 'Columns' },
/* Explicitly override the server data reduction to make it appropriate for matrix. */
dataReductionAlgorithm: { top: { count: 100 } }
},
values: {
for: { in: 'Values' }
}
}
}],

Rails, Highchart maps - adding custom data

I need some basic assistance with a Highmap (via Highcharts) I am trying to put in my Rails 4 app. I suspect I have some fundamental misunderstanding of it but can't find any clear guidance.
See a simple fiddle taken from the documentation, here
http://jsfiddle.net/SimonWalsh/zpdc1btu/
What I ultimately need to do is provide membership numbers for each country so that it will be displayed much the same as the population density is in this map.
I know I need to provide my data and the means to join it to the map data in
series : [{
data : data,
mapData: Highcharts.maps['custom/world'],
joinBy: ['iso-a2', 'code'],
name: 'Population density',
states: {
hover: {
color: '#BADA55'
}
}
}]
In this example, I am guessing that the data is being pulled from an external source and that the map data is the 'iso-a2' part of the array.
If this is the case, then why can't I supply this with my data....as an example see the added array with my data.....(just one example given for Denmark)
var mydata = [
{
"iso-a2": "dk",
"value": 30
},
]
and then do
series : [{
data : mydata,
mapData: Highcharts.maps['custom/world'],
joinBy: ['iso-a2', 'value'],
name: 'Population density',
states: {
hover: {
color: '#BADA55'
}
}
}]
This does not work.....any guidance at all (other than simply pointing me to docs would be greatly appreciated)
The joinBy specifies on which value you map a country with your data. With
joinBy: ['iso-a2', 'code']
you say that the 'iso-a2' value of the mapData should be equal to the 'code' value of your data. Therefore, your data must have this format:
var mydata = [
{
"code": "dk",
"value": 30
},
/* ... */
]