Angular 6 and Ag-grid - ag-grid

I'm doing a test with Angular 6 and Ag-Grid. I have done an example and it paints it, I mean the css and so on.
But by doing the example below and enter the real data from my Back-end does not paint the table and comes out all the time "loading"
// package.json
"dependencies": {
"ag-grid-angular": "^19.0.0",
"ag-grid-community": "^19.0.0",
// HTML
<div class="container-fluid">
Competencias
</div>
<div class="jumbotron text-center">
<ag-grid-angular #agGrid style="width: 100%; height: 200px;" class="ag-theme-balham" [gridOptions]="gridOptions">
</ag-grid-angular>
</div>
// COMPONENT
import { Component, OnInit } from '#angular/core';
import { environment } from '#env/environment';
import { CompetenceService } from '#app/services/competence.service';
import { GridOptions } from 'ag-grid-community';
#Component({
selector: 'app-competence',
templateUrl: './competence.component.html',
styleUrls: ['./competence.component.scss'],
providers: [CompetenceService],
})
export class CompetenceComponent implements OnInit {
version: string = environment.version;
title = 'app';
rowData: any;
columnDefs: any;
competences: any[];
gridOptions: GridOptions;
constructor(private competenceService: CompetenceService) { }
ngOnInit() {
this.gridOptions = <GridOptions>{};
this.gridOptions.columnDefs = new Array;
this.gridOptions.columnDefs = [
{
headerName: 'ID',
field: 'id',
width: 100
},
{
headerName: 'Nombre',
field: 'name',
width: 200
}];
this.competenceService.competences().subscribe(response => {
this.competences = response;
this.gridOptions.rowData = new Array;
this.competences.forEach((competence) => {
this.gridOptions.rowData.push({
id: competence.id, name: competence.desc
});
});
console.log(this.gridOptions);
});
}
}

First, you need to understand the flow:
rowData - is immutable - you can't manipulate with is as with array, you can just re-create it. More info
you need to avoid using gridOptions for any action - it's only for init-configuration, for anything else - you need to use gridApi - which could be accessed on onGridReady function
(gridReady)="onGridReady($event)"
...
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
let youData = [];
this.competences.forEach((competence) => {
youData.push({id: competence.id, name: competence.desc});
});
this.gridApi.setData(youData);
}

Try as below:
#Component({
selector: "my-app",
template: `<div style="height: 100%; 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"
[defaultColGroupDef]="defaultColGroupDef"
[columnTypes]="columnTypes"
[enableFilter]="true"
[floatingFilter]="true"
(gridReady)="onGridReady($event)"
></ag-grid-angular>
</div>`
})
export class AppComponent {
private gridApi;
private gridColumnApi;
private rowData: any[];
private columnDefs;
private defaultColDef;
private defaultColGroupDef;
private columnTypes;
constructor(private http: HttpClient) {
this.columnDefs = [
{
headerName: 'ID',
field: 'id',
width: 100
},
{
headerName: 'Nombre',
field: 'name',
width: 200
}
];
}
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
this.http
.get(
"https://raw.githubusercontent.com/ag-grid/ag-grid/master/packages/ag-grid-docs/src/olympicWinnersSmall.json"
)
.subscribe(data => {
this.rowData = data;
});
}

Related

ag-grid - space between column header and first row

There is a space between grid header row and first data row - how do i remove this? Thanks
My code:
<div>
<ag-grid-angular style="width: 500px; height: 500px;" [headerHeight]="0" [rowData]="rowData"
[rowSelection]="rowSelection" [rowMultiSelectWithClick]="true" [columnDefs]="columnDefs"
[floatingFiltersHeight]="0" (gridReady)="onGridReady($event)">
</ag-grid-angular>
</div>
columnDefs = [{
headerName: 'id', field: 'id', editable: true, suppressToolPanel: true, filter: false, hide: true
},
{
headerName: 'payrollcode', field: 'payrollcode', editable: true, suppressToolPanel: true, filter: false
},
{
headerName: 'select', field: 'select', editable: true, suppressToolPanel: true, filter: true, cellRendererParams: { checkbox: true }
}];
Please find code for screenshot gird below.
#Input()
displayObject: Array<any> = [];
#Input()
title = '';
columnDefs = [];
calcHeight$ = of(30);
loading$;
rowData = [];
constructor(
public activeModal: NgbActiveModal,
private calendarService: CalendarService,
private injector: Injector,
private modalService: NgbModal,
private sdToastService: SdToastService) { }
ngOnInit() {
Object.keys(this.displayObject[0]).forEach(key => {
this.columnDefs.push({ headerName: key, field: key, sortable: true, filter: true });
});
// this.rowData.concat(this.displayObject);
this.rowData = this.displayObject;
console.log(this.rowData);
}
<div style="width: 400px; height: 400px;">
<ag-grid-angular style="width: 600px; height:300px;" class="ag-theme-balham" [rowData]="rowData"
[columnDefs]="columnDefs">
</ag-grid-angular>
</div>
I added the code for the grid in the screenshot.
Here is a screenshot showing better the issue:
import { Component, Injector, Input, OnInit } from '#angular/core';
import { NgbActiveModal, NgbModal } from '#ng-bootstrap/ng-bootstrap';
import { of } from 'rxjs';
import { CalendarService } from '../calendar.service';
#Component({
selector: 'app-preview-calendars',
templateUrl: './preview-calendars.component.html',
styleUrls: ['./preview-calendars.component.css']
})
export class PreviewCalendarsComponent implements OnInit {
#Input()
displayObject: Array<any> = [];
#Input()
title = '';
columnDefs = [];
calcHeight$ = of(30);
loading$;
rowData = [];
constructor(
public activeModal: NgbActiveModal,
private calendarService: CalendarService,
private injector: Injector,
private modalService: NgbModal,
) { }
ngOnInit() {
Object.keys(this.displayObject[0]).forEach(key => {
this.columnDefs.push({ headerName: key, field: key, sortable: true, filter: true });
});
// this.rowData.concat(this.displayObject);
this.rowData = this.displayObject;
console.log(this.rowData);
}
}
<div style="width: 400px; height: 400px;">
<ag-grid-angular class="ag-theme-balham" [rowData]="rowData" [columnDefs]="columnDefs">
</ag-grid-angular>
</div>
You will see that the first row is occupies too much space and the last row is hidden - this is the issue it seems there is an empty row being displayed.
The data:
I had the exact same issue. I was embedding the grid in a prosemirror document. white-space: break-spaces is what broke ag-grid.
Setting white-space: normal !important fixed the header spacing issue.
Your problem may be caused by duplicate rows. Try adding a unique id for each element and adding getRowNodeId: data => data.id to the gridOptions.

How to capture the row hover event in ag-grid?

I was going through the documentation of ag-grid and looks like there is no event to capture the row hover event for the grid. My requirement is to display the image on the first column when the user hovers on the row. It might be on any column of the row, not necessarily the first cell. I'm using a cell-renderer and cell-editor and performing certain actions. (For simplicity, I didn't post the cell editor code in the plunker link) How can I achieve this?
Please see the plunkr example: https://plnkr.co/edit/NfuGp3iVheuCqglz
app.component.ts:
import { Component } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import {KaboobMenuComponent} from './kaboob-menu.component';
#Component({
selector: 'my-app',
template: `
<ag-grid-angular
#agGrid
style="width: 100%; height: 100%;"
id="myGrid"
class="ag-theme-alpine"
[columnDefs]="columnDefs"
[defaultColDef]="defaultColDef"
[rowData]="rowData"
(gridReady)="onGridReady($event)"
[frameworkComponents]="frameworkComponents"
></ag-grid-angular>
`,
})
export class AppComponent {
private gridApi;
private gridColumnApi;
private columnDefs;
private defaultColDef;
private rowData: [];
public frameworkComponents;
constructor(private http: HttpClient) {
this.columnDefs = [
{
headerName: 'Participant',
children: [
{
headerName: '',
filter: false,
sortable: false,
editable: true,
singleClickEdit: true,
cellRenderer: 'kaboobRenderer',
},
{ field: 'athlete' },
{
field: 'age',
maxWidth: 90,
},
],
},
{
headerName: 'Details',
children: [
{ field: 'country' },
{
field: 'year',
maxWidth: 90,
},
{ field: 'date' },
{ field: 'sport' },
],
}
];
this.defaultColDef = {
flex: 1,
minWidth: 150,
resizable: true,
};
this.frameworkComponents = {
kaboobRenderer: KaboobMenuComponent
};
}
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
this.http
.get(
'https://raw.githubusercontent.com/ag-grid/ag-grid/master/grid-packages/ag-grid-docs/src/olympicWinners.json'
)
.subscribe(data => {
this.rowData = data;
});
}
}
kaboob-menu.component.ts (My Custom Renderer):
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-kaboob-menu',
template: `<img border="0" width="15" height="10" src="https://raw.githubusercontent.com/ag-grid/ag-grid/master/grid-packages/ag-grid-docs/src/images/smiley.png"/>`,
})
export class KaboobMenuComponent implements OnInit {
params: any;
rowData: any;
display = true;
constructor() { }
agInit(params) {
this.params = params;
this.rowData = params.data;
}
ngOnInit() {
}
onClick($event) {
if (this.params.onClick instanceof Function) {
const params = {
event: $event,
rowData: this.params.node.data
};
this.params.onClick(params);
}
}
}
I'm using the cellMouseOver event, but this event is fired when we hover on the first column and not on any other columns. I want to capture the row hover event.
Any direction would be appreciated. Thanks in advance!
I also have similar requirement. I have used CSS styling and ag-grid class names to show the content of cell on row hover:
Initially hide the content of the cell by styling (display: none for that cell)
On row hover, ag-grid adds ag-row-hover CSS class, use this class selector to show the content of the cell.
Lets imagine your image class is my-image, so you have to define the styling as below:
.my-image {
display: none;
}
/* ag-grid adds ag-row-hover class on row hover */
.ag-row-hover .my-image {
display: initial;
}
For your example, you should define these styles in your kaboob-menu.component.ts ("My Custom Renderer")
Working plunker
I would listen to cellMouseOver event emitted by the grid.
In your html: (cellMouseOver)="onCellMouseOver($event)"
In your component:
onCellMouseOver(params) {
console.log(params.rowIndex); // 0
}
The params object has a rowIndex to identify which row it is on regardless of the cell. You can manipulate your rowNode inside this onCellMouseOver

Event listener works outside of the grid but doesn't work inside a cell in ag-grid

I have been struggling with making a simple listener work inside of a cell in ag-grid. What's bothering me is that it works perfectly if I place it in the html file.
In app.component.html:
<select class="form-control" (change)="
RefreshRisqueBrutColumn();"
>
<br>
<option>1- Très improbable</option>
<option>2- Peu probable</option>
<option>3- Possible</option>
<option>4- Probable</option>
</select>
In app.component.ts, I have the listener definition:
public RefreshRisqueBrutColumn() {
const params = { force: true };
this.gridApi.refreshCells(params);
console.log('LISTENER WORKS')
}
So in the browser, when I select an option:
I have this in the console:
Now, I have taken exactly the same select code and I have written it inside the custom cell renderer:
{
headerName: "Probabilité",
headerToolName: "Consultez les échelles",
field: "pbt",
editable: true,
cellRenderer: params => {
return `
<hr>
<select class="form-control" (change)="
RefreshRisqueBrutColumn();"
>
<br>
<option>1- Très improbable</option>
<option>2- Peu probable</option>
<option>3- Possible</option>
<option>4- Probable</option>
</select>
<hr>
`;
}
}
So here's the column in the browser:
So when I select an option, the same thing should happen, right?
However, nothing shows-up in the console.
So I am really curious why isn't this working?
And if possible, how can I fix it?
The cellRenderer expects plain string to be rendered for HTML. The string you are providing in your ColDef is actually an Angular template - which should be compiled into plain HTML. (observe (change)="RefreshRisqueBrutColumn())
Create custom CellRendererComponent, provide the template, define change handler within it and all will work fine.
Reference: Angular Cell Render Components
I have fixed this thanks #Paritosh's tip.
To save you some time, here's how I did it:
This is the custom cell renderer definition:
drop-down-cell-renderer.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-drop-down-cell-renderer',
templateUrl: './drop-down-cell-renderer.component.html',
styleUrls: ['./drop-down-cell-renderer.component.css']
})
export class DropDownCellRendererComponent implements OnInit {
constructor() { }
ngOnInit() {
}
params: any;
agInit(params: any): void {
this.params = params;
}
public RefreshRisqueBrutColumn() {
console.log('LISTENER WORKS')
}
}
drop-down-cell-renderer.component.html
<select class="form-control" (change)=" RefreshRisqueBrutColumn();">
<br>
<option>1- Très improbable</option>
<option>2- Peu probable</option>
<option>3- Possible</option>
<option>4- Probable</option>
</select>
app.module.ts
import {BrowserModule} from '#angular/platform-browser';
import {NgModule} from '#angular/core';
import {AppComponent} from './app.component';
import {AgGridModule} from 'ag-grid-angular';
import { DropDownCellRendererComponent } from './drop-down-cell-renderer/drop-down-cell-renderer.component';
#NgModule({
declarations: [
AppComponent,
DropDownCellRendererComponent
],
imports: [
BrowserModule,
AgGridModule.withComponents([DropDownCellRendererComponent])
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
app.component.ts
import {Component, OnInit} from '#angular/core';
import {NumberFormatterComponent} from './number-formatter.component';
import {NumericEditorComponent} from './numeric-editor.component';
import {RangeFilterComponent} from './range-filter.component';
import { DropDownCellRendererComponent } from './drop-down-cell-renderer/drop-down-cell-renderer.component';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
columnDefs = [
{
headerName: "Probabilité",
headerToolName: "Consultez les échelles",
field: "pbt",
editable: true,
cellRenderer: 'dropDownCellRendererComponent'
}
];
rowData = [{}];
frameworkComponents = {
dropDownCellRendererComponent: DropDownCellRendererComponent
};
ngOnInit() {
}
}
And here's the result:
Hope this helps someone :)

displaying a message in angular 6

hello I'm learning angular 6 but I don't understand why it doesn't display my message but he appears in the logs of my server.
component:
import { Component } from '#angular/core';
import { ChatService } from '../chat.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
message: string;
messages: string[] = [];
constructor(private chatService: ChatService) {
}
sendMessage() {
this.chatService.sendMessage(this.message);
this.message = '';
}
OnInit() {
this.chatService
.getMessages()
.subscribe((message: string) => {
this.messages.push(message);
});
}
}
html:
<div>
<li *ngFor="let message of messages">
{{message}}
</li>
</div>
<input [(ngModel)]="message" (keyup)="$event.keyCode == 13 && sendMessage()" />
<button (click)="sendMessage()">Send</button>
thanks for your help
chat service :
import * a io from 'socket.io-client';
import {Observable} from 'rxjs';
export class ChatService{
private url = 'http://localhost:3000';
private socket;
constructor() {
this.socket = io(this.url);
}
public sendMessage(message){
this.socket.emit('new-message',message);
}
public getMessage = () => {
return Observable.create((observer) => {
this.socket.on('new-message' , (message) => {
observer.next(message);
});
});
}
}

How to use Bootstrap accordion with angular2 (HTML5 mode/hashbag in angular2)

I'm trying to use bootstrap accordion but both (angular2 and bootstrap accordian) plays around hash location.
So is there something like html5 mode in angular2?
try this
/// <reference path="../../../typings/tsd.d.ts" />
import {
Component, View,
Directive, LifecycleEvent,
EventEmitter, ElementRef,
CSSClass, ViewContainerRef, TemplateRef
} from 'angular2/angular2';
// todo: support template url
#Component({
selector: 'accordion, [accordion]',
properties: [
'templateUrl',
'bCloseOthers: closeOthers'
]
})
#View({
template: `
<div class="panel-group">
<ng-content></ng-content>
</div>
`
})
export class Accordion {
private templateUrl:string;
private bCloseOthers:any;
private groups:Array<any> = [];
constructor() {
}
public closeOthers(openGroup:AccordionGroup) {
if (!this.bCloseOthers) {
return;
}
this.groups.forEach((group:AccordionGroup) => {
if (group !== openGroup) {
group.isOpen = false;
}
});
}
public addGroup(group:AccordionGroup) {
this.groups.push(group);
}
public removeGroup(group:AccordionGroup) {
let index = this.groups.indexOf(group);
if (index !== -1) {
this.groups.slice(index, 1);
}
}
}
#Directive({
selector: 'accordion-transclude, [accordion-transclude]',
properties: ['headingTemplate: accordion-transclude'],
lifecycle: [LifecycleEvent.onInit]
})
export class AccordionTransclude {
private headingTemplate: TemplateRef;
constructor(private viewRef: ViewContainerRef) {
}
onInit() {
if (this.headingTemplate) {
this.viewRef.createEmbeddedView(this.headingTemplate);
}
}
}
import {Collapse} from '../collapse/collapse';
// todo: support template url
// todo: support custom `open class`
#Component({
selector: 'accordion-group, [accordion-group]',
properties: [
'templateUrl',
'heading',
'isOpen',
'isDisabled'
],
host: {
'[class.panel-open]': 'isOpen'
},
lifecycle: [LifecycleEvent.onInit, LifecycleEvent.onDestroy]
})
#View({
template: `
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a href tabindex="0" class="accordion-toggle"
(^click)="toggleOpen($event)">
<span [class]="{'text-muted': isDisabled}"
[accordion-transclude]="headingTemplate">{{heading}}</span>
</a>
</h4>
</div>
<div class="panel-collapse collapse" [collapse]="!isOpen">
<div class="panel-body">
<ng-content></ng-content>
</div>
</div>
</div>
`,
directives: [Collapse, AccordionTransclude, CSSClass]
})
export class AccordionGroup {
private templateUrl:string;
private _isOpen:boolean;
public isDisabled:boolean;
public headingTemplate:any;
public templateRef: any;
constructor(private accordion:Accordion) {
}
onInit() {
this.accordion.addGroup(this);
}
onDestroy() {
this.accordion.removeGroup(this);
}
public toggleOpen(event:MouseEvent) {
event.preventDefault();
if (!this.isDisabled) {
this.isOpen = !this.isOpen;
}
}
public get isOpen():boolean {
return this._isOpen;
}
public set isOpen(value:boolean) {
this._isOpen = value;
if (value) {
this.accordion.closeOthers(this);
}
}
}
#Directive({
selector: 'accordion-heading, [accordion-heading]'
})
export class AccordionHeading {
constructor(private group:AccordionGroup, private templateRef: TemplateRef) {
group.headingTemplate = templateRef;
}
}
export const accordion:Array<any> = [
Accordion, AccordionGroup,
AccordionHeading, AccordionTransclude];