19

So I'm trying to setup ag-grid and I can't get one thing to work. I want to have a column that is actions. Then I want it to have a link or button that triggers a method in the component file.

For the column def I have the following. What am I doing wrong?

 {
    headerName: 'Actions',
    cellRenderer: params => {
      return `<a (click)="onEditClick("${params.data.hostname}")">Edit</a>`;
    }
 }
frido
  • 13,065
  • 5
  • 42
  • 56
Ponzi314
  • 215
  • 1
  • 2
  • 10

4 Answers4

21

I use cellRenderFramework:

    {
    headerName: '', width: 30,
    cellRendererFramework: ActionCellRendererComponent,
    cellRendererParams: {
      icon: 'fa-download',
      action: this.downloadAttachmentAction
    }
  }

and than I have custom Component

@Component({
  selector: 'cu-download-link-cell-renderer',
  template: `
  <div class="text-center">
    <i class="fa {{params.icon}}" (click)="onClick()" aria-hidden="true"></i>
  </div>`
})
export class ActionCellRendererComponent {

    params;

    constructor() {
    }

    agInit(params): void {
        this.params = params;
        if (_.isNil(params.action)) {
            throw new Error('Missing action parameter for ActionCellRendererComponent');
       }
   }

   onClick(): void {
       this.params.action(this.params);
   }
}

export type CellAction = (params) => void;
Peter1982
  • 518
  • 2
  • 11
  • Great Example! But this assumes my ColDef's are defined directly in my component. If I have abstracted out my ColDef's into a separate class, do you have a suggestion how I would reference the `action` function that might still live on the component? – luker02 Aug 24 '18 at 14:32
  • @luker02 Did you find any solution for this without create a custom cellrender component? – Lucas Santos Apr 03 '19 at 22:07
  • 2
    @LucasSantos No, I did create a cellrenderer component. Then instead of directly calling my component function using the `action` param, I emitted events from the cellrenderer component and listened for them on my main component – luker02 Apr 04 '19 at 21:58
  • hi @Peter1982, what is used of agInit() function? – Fai Zal Dong Aug 13 '19 at 04:58
  • @FaiZalDong components for AgGrid extends AgFrameworkComponent. Function agInit() is similar to ngOnInit(). – Peter1982 Aug 13 '19 at 15:15
  • what did you added `export type CellAction = (params) => void;` at the end? is that required? – harishr May 09 '20 at 14:53
  • This almost works, but unfortunately loses the component context when it calls back the function. Better to also pass the component context to the cell renderer. – iGanja Oct 06 '21 at 01:48
8

Use cellRendererFramework to add action Buttons.

App.component.ts

columnDefs = [
  { headerName: 'First Name', field: 'firstName', sortable: true, filter: true },
  { headerName: 'Last Name', field: 'lastName', sortable: true, filter: true },
  { headerName: 'Email', field: 'email', sortable: true, filter: true },
  { headerName: 'User Name', field: 'userIdName', sortable: true, filter: true },
  { headerName: 'Role', field: 'role', sortable: true, filter: true },
  { headerName: 'Actions', field: 'action', cellRendererFramework: CellCustomComponent }];

rowData: any;

ngOnInit() {
  const empDatas = localStorage.getItem('user');
  const finalData = JSON.parse(this.empDatas);
  this.rowData = this.finalData;
}

In the above code, we can see CellCustomComponent. Create that component & add the buttons.

cell-custom.component.html

<button type="button" class="btn-success" (click)="editRow()">Edit</button>
<button type="button" class="btn-success" (click)="viewRow()">View</button>

Now in the cell-custom.component.ts add the functions

cell-custom.component.ts

export class CellCustomComponent implements OnInit {
  data: any;
  params: any;
  constructor(private http: HttpClient, private router: Router) {}

  agInit(params) {
    this.params = params;
    this.data = params.value;
  }

  ngOnInit() {}

  editRow() {
    let rowData = this.params;
    let i = rowData.rowIndex;
    console.log(rowData);
  }

  viewRow() {
    let rowData = this.params;
    console.log(rowData);
  }
}

After this we need to add this component in App.module.ts

app.Module.ts

@NgModule({
  declarations: [AppComponent, CellCustomComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    HttpClientModule,
    AgGridModule.withComponents([AppComponent])
  ],
  providers: [],
  entryComponents: [CellCustomComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

Now we can trigger a method in the component file using Button.

Ag-Grid Angular 7

Walter Luszczyk
  • 1,369
  • 2
  • 19
  • 36
Jerold Joel
  • 227
  • 1
  • 9
  • 22
1

it has been perfect! Thank you

prebilling-view.component.ts (cellRendererParams: { context: this })

 {
field: 'adjustmentUnit',
  tooltipField: 'adjustmentUnit',
  cellRendererParams: { context: this },
  cellRendererSelector: (params: any) => {
    const component = {
      component: 'textAreaVueRenderer',
      params: { values: true, textAlign: 'right', typeValue:false}
    }
    return component;
  },
  cellStyle: { textAlign: 'right' },
  headerClass: 'textRight',
},

function in prebilling-view.component.ts

onEditChange(val:string, index:any){
console.log("valor: "+ val)
console.log("index: "+ index)

}

input cellRenderSelector textAreaVueRender

  <input *ngIf="editEnabled"
            type="number"
            (input)="inputNegativeChangeHandler($event)"/>

function in cellRenderSelector textAreaVueRender component

 inputNegativeChangeHandler($event: any) {

this.params.context.onEditChange($event.target.value,this.params.rowIndex);

}

Mike Mahan
  • 11
  • 2
  • Please don't add "thank you" as an answer. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation), you will be able to [vote up questions and answers](https://stackoverflow.com/help/privileges/vote-up) that you found helpful. - [From Review](/review/late-answers/30439986) – IDK4real Nov 26 '21 at 21:38
0

Yes, use the cellRendererFramework to handle the rendering.

In your columnDefs:

this.columnDefs = [
  {
    headerName: 'Header Name', field: 'field',
    cellRendererFramework: ColRenderer,
    cellRendererParams: { context: this },
    sortable: true, filter: true
  },
  ...
 ];

Then in your ColRenderer:

@Component({
  template: `<a (click)="clickHandler(rowData)">{{rowData.Member}}</a>`
})
export class ColRenderer implements ICellRenderer {
  public rowData: any;
  private params: any;

  public agInit(params: { data: any, context: any }) {
    this.rowData= params.data;
    this.params = params;
  };

  public clickHandler(data: any) {
    this.params.context.onEditClick(data);
  }
  ...
}

Change the names above obviously as needed. Just know the context is the key. You pass the context of your component to the renderer then use that context to call the function you want on click within your renderer.

iGanja
  • 2,374
  • 2
  • 28
  • 32