Select ag-grid row programmatically on load - ag-grid

Input button - Is used to send a parameter back to stored proc to
fetch new data. (In the demo you don't need to put any value in there)
Reload Button - Is used to fetch new data based on the parameter.
I need to select some rows based on some condition from the service data. Rows get selected for the first time but when I reload the service data the rows get selected and then gets unselected automatically. Please check in the below plunker.
First time - Click Reload Button - Grid Loads Fine.
Second time - Click the Reload Button - Rows gets selected and then gets unselected soon after.
#Component({
selector: "my-app",
template: `<div style="height: 100%; padding-top: 35px; box-sizing: border-box;">
<ag-grid-angular
#agGrid
style="width: 100%; height: 100%;"
id="myGrid"
[rowData]="rowData"
class="ag-theme-balham"
[columnDefs]="columnDefs"
[defaultColDef]="defaultColDef"
[enableColResize]="true"
[suppressRowClickSelection]="true"
[rowSelection]="rowSelection"
(gridReady)="onGridReady($event)"
></ag-grid-angular>
</div>
<div style="position: absolute; top: 0px; left: 0px;">
<input type="Text" placeholder="Param to SP"/>
<button (click)="reloadData()">ReloadData</button>
</div>`
})
export class AppComponent {
private gridApi;
private gridColumnApi;
private rowData: any[];
private columnDefs;
private defaultColDef;
private rowSelection;
constructor(private http: HttpClient) {
this.columnDefs = [
{
headerName: "Athlete",
field: "athlete",
headerCheckboxSelection: true,
headerCheckboxSelectionFilteredOnly: true,
checkboxSelection: true
},
{
headerName: "Age",
field: "age"
},
{
headerName: "Country",
field: "country"
},
{
headerName: "Year",
field: "year"
},
{
headerName: "Date",
field: "date"
},
{
headerName: "Sport",
field: "sport"
},
{
headerName: "Gold",
field: "gold"
},
{
headerName: "Silver",
field: "silver"
},
{
headerName: "Bronze",
field: "bronze"
},
{
headerName: "Total",
field: "total"
}
];
this.defaultColDef = { width: 100 };
this.rowSelection = "multiple";
}
reloadData() {
this.http
.get("https://raw.githubusercontent.com/ag-grid/ag-grid-docs/master/src/olympicWinnersSmall.json")
.subscribe(data => {
this.rowData = data;
});
this.gridApi.forEachNode(function (node) {
node.setSelected(true);
});
}
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
}
}
Plunker - https://plnkr.co/edit/fuJ4DBc7Slp8MUTEKolJ?p=preview

The issue was angular was trying to bind the properties columndefs and rowdata on its own in random order, thus columndefs was getting called after and all the selected rows were getting de-selected.
The solution to the problem is don't bind columndefs and rowdata directly as a property to ag-grid instead, use gridOptions and set columndefs and rowdata using the API.
#Component({
selector: "my-app",
template: `<div style="height: 100%; padding-top: 35px; box-sizing: border-box;">
<ag-grid-angular
#agGrid
style="width: 100%; height: 100%;"
id="myGrid"
[gridOptions]="gridOptions"
class="ag-theme-balham"
[enableColResize]="true"
[suppressRowClickSelection]="true"
[rowSelection]="rowSelection"
(gridReady)="onGridReady($event)"
></ag-grid-angular>
</div>
<div style="position: absolute; top: 0px; left: 0px;">
<input type="Text" placeholder="Param to SP"/>
<button (click)="reloadData()">ReloadData</button>
</div>`
})
this.gridOptions.api.setColumnDefs(this.createParentColumnDefs());
this.gridOptions.api.setRowData(this.createParentRowData());

Related

AG Grid: center checkbox alone in cell

Versions:
vueJS: 3.0.0
bootstrap: 5.0.0-beta3
ag-grid-community: 26.1.0
ag-grid-vue3: 26.1.2
See screenshot below. In my columnDefs for ag-grid, I have specified checkboxSelection: true for the Pending column. I do not wish to render any text in that column. Rather, I wish for a single checkbox that is centered in each cell. Can this be done? As things stand now, the checkbox is left-aligned in the cell.
Here is the columnDef for Pending:
{ headerName: "Pending", field: "pending", sortable: true, editable: true, checkboxSelection: true, cellStyle: () => getPageStatus() },
And here is styling for column headers:
.ag-header-cell-label {
justify-content: center;
}
Thanks for looking into it.
I scratched up a general solution that explains how to render custom HTML elements within a grid cell. Most of this solution is based on pre-existing articles and blogs out there. Note the data model here (rendered to the grid) assumes a pending property.
<template>
<ag-grid-vue
class="ag-theme-alpine"
:frameworkComponents="frameworkComponents"
:columnDefs="columnDefs"
:rowData="getRowData"
rowSelection="multiple"
domLayout="autoHeight"
editType="fullRow"
#grid-ready="onGridReady">
</ag-grid-vue>
<script>
import CheckboxRenderer from '#/components/CheckboxRenderer.vue';
export default {
data() {
return {
frameworkComponents: {
checkboxRenderer: CheckboxRenderer
},
columnDefs: [
{ headerName: "Pending", field: "pending", sortable: true, editable: true,
cellStyle: () => getPageStatus(), cellRenderer: 'checkboxRenderer', valueGetter: params => params ? null : null },
]
}
}
};
CheckboxRenderer.vue
<template>
<input ref="eGui" #click="checkedHandler" type="checkbox" v-model="params.data.pending" class="ag-input-field-input ag-checkbox-input" />
</template>
<script>
export default {
name: "CheckboxRenderer",
props: {
params: Object
},
methods: {
getGui() {
return this.$refs.eGui;
},
checkedHandler(e) {
let checked = e.target.checked;
let colId = this.params.column.colId;
this.params.node.setDataValue(colId, checked);
}
},
};
</script>
<style>
.ag-checkbox-input {
width: 18px;
height: 18px;
vertical-align: middle;
}
</style>

How to resize chart.js graph dynamically for responsive sites?

Hej,
I know this has been answered in one way or the other many times, but I really can't get it work in my context with flex-boxes.
I have fixed elements, such as headers and footers on my page, and a chart that shall take up all the remaining space in between. While it appears to be working on first glance, you can see that the text and numbers are blurred and not properly scaled when the window is resized.
How can I fix this, or have chart.js redraw the canvas upon resize?
Check out my fiddle
https://jsfiddle.net/fg9pd1b3/
<body>
<div class="container">
<div class="fixed">
header
</div>
<div id="chartcontainer">
<canvas id="chartJSContainer"></canvas>
</div>
<div class="fixed">
footer
</div>
</div>
</body>
CSS:
html,
body {
height: 100vh;
min-height: 100vh;
max-height: 100vh;
margin: 0;
padding: 0;
}
.container {
width: 80%;
height: 100%;
margin: 0 auto;
display: flex;
flex-direction: column;
flex-basis: 100%;
flex-grow: 1;
background: #CCC;
}
.p {
text-align: center;
font-size: 14px;
padding-top: 140px;
}
.fixed {
background: black;
height: 100px;
min-height: 100px;
color: white;
text-align: center;
}
#chartcontainer {
position: relative;
min-height: 200px;
display: flex;
flex-grow: 1;
}
canvas {
width: 100% !important;
height: 100% !important;
}
JS:
Chart.defaults.global.responsive = true;
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
reverse: false
}
}]
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
You have given fixed min-height to the canvas div which restricts the chart to further change it's dimensions. So, the following code has auto height and width automates to 100% which gives flexible chart.
#chartcontainer {
position:relative;
min-height:auto;
width:100%;
display: flex;
flex-grow:1;
}

Center buttons in flex in Appbar

I have trouble aligning/justifying as centered buttons in the AppBar.
It looks like this (see demo here):
<AppBar position='sticky'>
<Toolbar>
<div className={classes.topMenuBoxes}>
<img className={classes.logoSize} src={LogoFull} alt="logo" ></img>
</div>
<div className={classes.topMenuBoxes}>
<Button className={classes.menuText} color='inherit' >Offer</Button>
<Button className={classes.menuText} color='inherit' >Join</Button>
<Button className={classes.menuText} color='inherit' component={AboutLink}>About us</Button>
</div>
<div className={classes.topMenuBoxes}>
<DropMenu />
</div>
</Toolbar>
</AppBar>
...and using this makeStyles:
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
},
logoSize: {
marginTop: '30px',
height: '70px',
},
menuButton: {
[theme.breakpoints.up('md')]: {
display: 'none',
},
marginRight: theme.spacing(2),
},
menuText: {
[theme.breakpoints.down('sm')]: {
display: "none",
},
textTransform: 'none',
},
topMenuBoxes: {
flex: 1,
},
}));
How do I align content inside the divs where I have referenced classes.topMenuBoxes?
Thanks!
Add textAlign:"center" to your topMenuBoxes:
const useStyles = makeStyles(theme => ({
// ...
topMenuBoxes: {
flex: 1,
textAlign: "center"
}
}));

how to use multiple custom components in framework in ag-grid-angular?

I have created two custom components, i.e custom tooltip component and custom datepicker component. when im trying to declare in framework it is not working.
Its taking only datepicker custom component not tooltip component. If datepicker component is removed then its taking tooltip component Its considering only one custom component in frameworkComponent.
Please find the below code:
CustomTooltip :
import {Component, ViewEncapsulation} from '#angular/core';
import {ITooltipAngularComp} from "ag-grid-angular";
#Component({
selector: 'tooltip-component',
template: `
<div class="custom-tooltip" [style.background-color]="data.color">
<p>{{tooltipData}}</p>
</div>`,
styles: [
`
:host {
position: absolute;
width: 250px;
height: 60px;
border: 1px solid cornflowerblue;
overflow: hidden;
pointer-events: none;
transition: opacity 1s;
}
:host.ag-tooltip-hiding {
opacity: 0;
}
.custom-tooltip p {
margin: 5px;
white-space: nowrap;
}
`
],
styleUrls: ['./custom-tooltip.component.scss']
})
export class CustomTooltip implements ITooltipAngularComp {
params: any;
data: any;
tooltipData: any;
agInit(params): void {
console.log("params",params.value);
this.params = params;
this.tooltipData=params.value;
this.data = params.api.getRowNode(params.rowIndex).data;
this.data.color = this.params.color || 'white';
}
}
CustomDateComponent:
import {Component, ElementRef, ViewChild} from '#angular/core';
import flatpickr from 'flatpickr'
#Component({
selector: 'app-loading-overlay',
template: `
<div #flatpickrEl class="ag-input-text-wrapper custom-date-filter fa">
<input type='text' data-input />
<a class='input-button' title='clear' data-clear>
<i class='fa fa-times'></i>
</a>
<a class="input-button" title="toggle" data-toggle>
<i class="fa fa-calendar"></i>
</a>
</div>
`,
styles: [
`
.custom-date-filter a {
position: relative;
right: 34px;
color: rgba(0, 0, 0, 0.54);
cursor: pointer;
}
.custom-date-filter:after {
content: '\f073';
display: block;
font-weight: 400;
font-family: 'Font Awesome 5 Free';
position: relative;
right: 25px;
pointer-events: none;
color: rgba(0, 0, 0, 0.54);
}
`
]
})
export class CustomDateComponent {
#ViewChild("flatpickrEl", {read: ElementRef}) flatpickrEl: ElementRef;
private date: Date;
private params: any;
private picker: any;
agInit(params: any): void {
this.params = params;
}
ngAfterViewInit(): void {
// outputs `I am span`
this.picker = flatpickr(this.flatpickrEl.nativeElement, {
onChange: this.onDateChanged.bind(this),
wrap: true
});
this.picker.calendarContainer.classList.add('ag-custom-component-popup');
}
ngOnDestroy() {
console.log(`Destroying DateComponent`);
}
onDateChanged(selectedDates) {
this.date = selectedDates[0] || null;
this.params.onDateChanged();
}
getDate(): Date {
return this.date;
}
setDate(date: Date): void {
this.date = date || null;
this.picker.setDate(date);
}
}
Im trying to use both custom component in one grid i.e:
this.columnDefs = [
{
headerName: 'Request Number', field: 'request_no', sortable: true, filter: 'agNumberColumnFilter'
},
{
headerName: 'Request Date', field: 'created_at', sortable: true, width: 300,
filter: "agDateColumnFilter",
filterParams: {
comparator: function (filterLocalDateAtMidnight, cellValue) {
var dateAsString = cellValue;
var dateParts = dateAsString.split("/");
var cellDate = new Date(Number(dateParts[2]), Number(dateParts[1]) - 1, Number(dateParts[0]));
if (filterLocalDateAtMidnight.getTime() === cellDate.getTime()) {
return 0;
}
if (cellDate < filterLocalDateAtMidnight) {
return -1;
}
if (cellDate > filterLocalDateAtMidnight) {
return 1;
}
}
}
},
{ headerName: 'Requested By', field: 'user_name', sortable: true, filter: 'agTextColumnFilter', tooltipField: 'user_name' },
{
headerName: 'Client', field: 'borrower_name', sortable: true, filter: 'agTextColumnFilter',
tooltipField: 'borrower_name', tooltipComponentParams: { color: "#ececec" }, width: 200
},
{
headerName: 'Debtor', field: 'customer_name', sortable: true, filter: 'agTextColumnFilter',
cellStyle: { color: 'blue', cursor: 'pointer' }, tooltipField: 'customer_name', width: 200
},
{
headerName: 'Current Limit', field: 'current_limit', sortable: true, filter: 'agNumberColumnFilter',
cellStyle: { textAlign: 'right' },
cellRenderer: this.CurrencyCellRenderer
},
{
headerName: 'Requested Limit', field: 'requested_limit', sortable: true, filter: 'agNumberColumnFilter',
cellStyle: { textAlign: 'right' },
cellRenderer: this.CurrencyCellRenderer
},
{
headerName: 'Approved Limit', field: 'approved_limit', sortable: true, filter: 'agNumberColumnFilter',
cellStyle: { textAlign: 'right' },
cellRenderer: this.CurrencyCellRenderer
},
{ headerName: 'Status', field: 'status', sortable: true, filter: 'agTextColumnFilter', width: 120, },
{ headerName: 'Comment', field: 'comment', sortable: true, filter: 'agTextColumnFilter', tooltipField: 'comment', width: 200 },
{
headerName: "",
suppressMenu: true,
suppressSorting: false,
cellClass: 'action-class',
width: 120,
template:
`<i class="fa fa-pencil-square-o" aria-hidden="true" data-action-type="view" pTooltip="Edit Queue" tooltipPosition="top"></i>
<i class="fa fa-info-circle" aria-hidden="true" data-action-type="history" pTooltip="View Comment History" tooltipPosition="top"></i>`
}
];
this.defaultColDef = {
enableValue: true,
sortable: true,
tooltipComponent: "customTooltip",
resizable: true
};
this.frameworkComponents = {
customTooltip: CustomTooltip,
agDateInput: CustomDateComponent };
Seems it's a custom tooltip issue (somewhere inside ag-grid), will try to inform the team and describe the bug.
In your case, you can specify your component (CustomDateComponent) directly via cellEditorFramework rather than cellEditor, without internal declaration in frameworkComponents block.
{
headerName: "Date",
field: "date",
width: 190,
editable:true,
cellEditorFramework:CustomDateComponent
}
Just for info: your CustomDateComponent not yet ready to be used as cellEditor

Echarts - Scrollbar outside the canvas

I am using echarts library for bar charts. I want scrollbar to display outside the canvas. Is there any way I can accomplish this?
Unfortunately, Echarts don't support scrollbar option.
However you can simply achieve this use a wrap DOM.
check this demo:
let echartsObj = echarts.init(document.querySelector('#canvas1'));
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar'
}]
};
echartsObj.setOption(option)
echartsObj = echarts.init(document.querySelector('#canvas2'));
option = {
xAxis: {},
yAxis: {},
series: [{
symbolSize: 20,
data: [
[10.0, 8.04],
[8.0, 6.95],
[13.0, 7.58],
[9.0, 8.81],
[11.0, 8.33],
[14.0, 9.96],
[6.0, 7.24],
[4.0, 4.26],
[12.0, 10.84],
[7.0, 4.82],
[5.0, 5.68]
],
type: 'scatter'
}]
};
echartsObj.setOption(option)
.echart-wrap {
display: inline-block;
width: 300px;
height: 300px;
overflow: scroll;
border: 1px solid black;
}
<html>
<header>
<script src="https://cdn.bootcss.com/echarts/4.1.0.rc2/echarts-en.min.js"></script>
</header>
<body>
<div class="echart-wrap">
<div id="canvas1" style="width: 500px; height: 500px">
</div>
</div>
<div class="echart-wrap">
<div id="canvas2" style="width: 500px; height: 500px">
</div>
</div>
</body>
</html>