Utilizing ag-grid with Vue.js: Implementing TypeScript to access parent grid methods within a renderer

I've integrated ag-grid into my project and added a custom cell renderer: https://www.ag-grid.com/javascript-grid-cell-rendering-components/#example-rendering-using-vuejs-components

Although the renderer is working well, I'm facing an issue where I can't access parent grid methods like shown in the example above (i.e.

this.params.context.componentParent.methodFromParent(...);
)

The cell renderer is responsible for customizing cell rendering and interactions:

Template => ActionCellRenderer.vue:

<template>
    <span v-if="isPending() && !isConfirmed">
        <v-btn v-if="!isAskingForConfirmation"
               v-on:click="askForConfirmation"
               depressed small
               class="button">
            <v-icon class="icon">undo</v-icon> Cancel
        </v-btn>

        <v-btn v-else
               v-on:click="confirm"
               depressed small
               class="button" >
            <v-icon class="icon">error_outline</v-icon> Are you sure?
        </v-btn>
    </span>
</template>

<style>
    .button {
        margin: 0;
        font-size: .72rem;
    }

    .icon {
        font-size: 1.3rem;
    }
</style>

<script lang="ts" src="./ActionCellRenderer.ts">
</script>

Logic => ActionCellRenderer.ts :

@Component
export default class ActionCellRenderer extends Vue {

    public isAskingForConfirmation = false;
    public isConfirmed = false;

    isPending(): boolean {
        // @ts-ignore
        return this.params.value === "Pending";
    }

    askForConfirmation(): void {
        // @ts-ignore
        this.isAskingForConfirmation = true;
        // @ts-ignore
        console.log(this.params);
        window.setTimeout(()  => {
            this.isAskingForConfirmation = false;
        }, 3000);
    }

    confirm(): void {
        alert("Confirmed!");
        this.isConfirmed = true;
    }
}

The parent grid:

Template => CashoutRecords.vue:

<template>
  <ag-grid-vue
    class="ag-theme-balham"
    domLayout="autoHeight"
    :columnDefs="columnDefs"
    :defaultColDef="defaultColDef"
    :frameworkComponents="frameworkComponents"
    :rowData="cashoutRecords"
:gridOptions="gridOptions"
@grid-ready="onGridReady"
></ag-grid-vue>
</template>

<style>
  .ag-row .ag-cell {
    display: flex;
    align-items: center;
  }
</style>

<script lang="ts" src="./CashoutRecords.ts">
</script>

Logic => CashoutRecords.ts:

@Component({
    components: {
        AgGridVue,
    },
})
export default class CashoutRecords extends Vue {

    @NS.Action(Actions.fetchCashouts) fetchCashouts!: ActionTypes.fetchCashouts;
    @NS.Action(Actions.fetchCompanies) fetchCompanies!: ActionTypes.fetchCompanies;
    @NS.Getter(Getters.cashoutRecords) cashoutRecords!: GetterTypes.cashoutRecords;

    gridOptions: GridOptions = {
        rowHeight: 45,
    };

    frameworkComponents = {
        actionCellRenderer: ActionCellRenderer,
    };

    columnDefs: ColDef[] = [
        {
            headerName: "",
            filter: true,
            pinned: "right",
            field: "state.name",
            width: 130,
            resizable: true,
            cellRenderer: "actionCellRenderer",
        },
        { headerName: "Date", field: "createdOn", valueFormatter: this.dateTimeFormatter, width: 150, resizable: true },
        { headerName: "Recipient", field: "recipient", resizable: true },
        { headerName: "Amount", field: "amount", valueFormatter: this.currencyFormatter, width: 110, resizable: true },
        { headerName: "Label", field: "comment", resizable: true },
        { headerName: "State", field: "state.name", width: 100, resizable: true },
        { headerName: "Created by", field: "createdBy", resizable: true },
    ];

    defaultColDef = { filter: true };

    private gridApi!: GridApi;

    mounted() {
        if (this.gridOptions.api) {
            this.gridApi = this.gridOptions.api;
        }
    }

    async onGridReady() {
        await this.loadCashoutRecords();
    }

    async loadCashoutRecords() {
        this.gridApi.showLoadingOverlay();
        await Promise.all([
            this.fetchCompanies(),
            this.fetchCashouts(),
        ]);
        if (this.cashoutRecords.length === 0) {
            this.gridApi.showNoRowsOverlay();
        } else {
            this.gridApi.hideOverlay();
        }
    }

    private methodFromParent(cell: any) {
        alert("Parent Component Method from " + cell + "!");
    }

    private currencyFormatter(params: ValueFormatterParams) {
        return toCurrency(params.value);
    }

    private dateTimeFormatter(params: ValueFormatterParams) {
        return toDateTime(params.value);
    }
}

When calling console.log(this.params); within the askForConfirmation method, the 'context' field doesn't appear:

Object
$scope = null
addRenderedRowListener = function (eventType, listener) {
...

Is there a way to access the grid method methodFromParent from the cell renderer?

Answer №1

It turned out to be a simple fix - I just needed to declare the context and methods fields, which I mistakenly assumed were built-in.

In short:

Logic => CashoutRecords.ts:

context = { componentParent: this };
methods = {
    async methodFromParent(cell: any) {
        // ... implementation goes here
    }
};

Don't forget to reference that context in the template:

Template => CashoutRecords.vue:

<template>
  <ag-grid-vue
    ...
    :context="context"
...
></ag-grid-vue>
</template>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Differences between addEventListener and jQuery's on method, as well as form.submit and jQuery's

I encountered a situation where callbacks registered using jQuery's on method were not being called when trying to trigger form submission with the HTML Form element object instead of jQuery. After some testing, I discovered that changing the code to ...

Error: authentication failed during npm installation due to an incorrect URL

After executing npm install @types/js-cookie@^2.2.0, an error occurred: npm install @types/js-cookie@^2.2.0 npm ERR! code E401 npm ERR! Unable to authenticate, need: Basic realm="https://pkgsprodsu3weu.app.pkgs.visualstudio.com/" npm ERR! A com ...

JavaScript - Navigating through JSON object in reverse (from leaf to root) direction

FamilyTree= { "name":"Family", "photo":"images/family.jpg", "members":[ { "name":"Parent", "photo":"images/parent.jpg", "relationships":[ { "name":"Spouse", "photo":"images/spouse.jpg" }, ...

"Troubleshooting 3D Models not appearing correctly in Mapbox when using Three.js

My issue lies in the inability to load any .gltf file, only a standard one. For further details, please continue reading. The map on my application showcases a 3D model indicated by the red arrow: https://i.sstatic.net/3Ce09.png The model is a GLTF file ...

How to Use jQuery in Thymeleaf to Toggle All Checkboxes

Why isn't the function of selecting and deselecting all fields working correctly for me? Can anyone explain what may be causing this issue? ..... <head> <meta name="viewport" content="width=device-width, initial-scale=1.0&q ...

Tips for escaping an infinite loop within the componentDidUpdate function in reactjs

Currently, I am working on creating dashboards using reactjs. I have successfully implemented 4 tabs or buttons for charts, but I am facing an issue when clicking on different dashboards that have the same chart in the same panel. The chart is not updating ...

Mapping an array of objects within another array of objects

I have a collection of objects that I looped through to extract the content: const teamSliderContent = [ { Description1: 'Chef. Mordy Wenk', Title: 'Head of the Chief staff.', id: 1, }, { Desc ...

tslint issues detected within a line of code in a function

I am a novice when it comes to tslint and typescript. Attempting to resolve the error: Unnecessary local variable - stackThird. Can someone guide me on how to rectify this issue? Despite research, I have not been successful in finding a solution. The err ...

What steps should be followed to incorporate a horizontal scrollbar within the table's header?

I'm currently using Vue and Vuetify to create a unique layout that looks like this: https://i.stack.imgur.com/QBs3J.png The layout consists of a card with three rows: The first row displays the number of items and includes a search bar. The second ...

Using grid-template-areas in ReactJS function components does not function as expected

REMINDER: Check out and customize the code in CodeSandbox. This is a parent component with 5 children elements. Among them, 3 are React components and the remaining 2 are regular HTML buttons: import "./App.css"; import React from "react&qu ...

Transferring properties from the main layout to a specific component

Recently delving into the world of Vue, I find myself in need of passing props from a layout to a global component. Although my search skills may not be up to par, I have been tinkering with a default layout setup as follows: layouts/default.vue <templ ...

Angular - Showing validation messages post successful execution of two functions

I have encountered an issue with my form submission process involving two functions. When both functions succeed, I want to display a successful validation message. However, currently the success message is displayed even if the second function fails. How ...

Is there a way to update a JSON file using React?

I'm looking for a solution to update a JSON file in React. Is it possible? Below is the code snippet that executes when an HTML element is clicked. Ultimately, it invokes VoteTracking, the function responsible for updating the JSON file. handleC ...

Encountered an Error with My Protractor Script - Object Expected

Currently, I am in the process of learning automation testing for an AngularJS application. However, I have encountered an "object expected" error on line 4, which is pointing to the first line of my script. describe("Homepage", function() { it("Navig ...

Is it possible to integrate jQuery and JavaScript together?

Can I combine JavaScript selector document.querySelector with jQuery functions instead of using $ or jQuery selectors? For instance: $.getJSON("list.json", function(data) { document.querySelector("#content").html(data.name); }); When trying to use d ...

What are the best practices for preventing risky assignments between Ref<string> and Ref<string | undefined>?

Is there a way in Typescript to prevent assigning a Ref<string> to Ref<string | undefined> when using Vue's ref function to create typed Ref objects? Example When trying to assign undefined to a Ref<string>, an error is expected: co ...

Dynamically load current components in Angular 2's final release

In my quest to dynamically load a component in the upcoming release version 2.0.0, I encountered some challenges. Previously, in RC5, I utilized the following code for loading: I created a directive responsible for loading the controls: import { Check ...

Is it feasible to execute exe files within a ReactJS environment?

Hey there! I've created a Game Launcher using ReactJS for my Unity game and was wondering if it's feasible to start the game (an exe file) simply by clicking on the play button. Can anyone please advise me on this? ...

Sending a personalized event to a JavaScript object

I am looking to create an object Constructor that can dispatch a customEvent, which I then want to listen to from the instance of the object. The code snippet provided showcases what I have been attempting. I would appreciate any assistance on how to mak ...

Tips for implementing a null check within the findAll() function

I am inquiring about the database and some parameters on the request body are optional. Can someone please guide me on how to determine if certain fields, like categoryId, are nullable and perform the where query based on that? var categoryId = req.body ...