Switching cell icon when clicked - A step-by-step guide

I have a situation in ag-grid where I need to update the icon of a button in a cell when it is clicked to indicate progress and then revert back to its original state upon completion of the action.

Below is the code snippet:

my-custom.component.ts

  <ColDef>{
    headerName: 'Export',
    width: 40,
    height: 80,
    cellRendererFramework: ButtonCellRendererComponent,
    cellRendererParams: {
      isLoading: false,
      onClick: this.onExportButtonClicked.bind(this),
    }
  }

onExportButtonClicked(cell) {
    this.customService.downloadData(cell.rowData)
      .subscribe(data => {console.log("success")},
        (error) => { console.log("there was an error") },
        () => {
          console.log("complete function triggered");
        });
  }



template: `<button class="unstyled-button" (click)="onClick($event)">
            <span *ngIf="!isLoading">
                <i class="fas fa-file-pdf"></i>
            </span>
            <span *ngIf="isLoading">
            <i class="fas fa-spinner fa-spin"></i>
            </span>
          </button>`,
export class ButtonCellRendererComponent implements ICellRendererAngularComp {
    public isLoading: boolean;

    private params: any;

    agInit(params: any): void {
        this.params = params;
        this.isLoading = this.params.isLoading;

    }
    refresh(params: any): boolean {
        return false;
    }

    onClick($event) {
        if (this.params.onClick instanceof Function) {
            const params = {
                event: $event,
                data: this.params.node.data,
                isLoading: this.isLoading
            }
            this.params.onClick(params)

        }
    }

What is the best way to toggle the isLoading variable in this scenario? Can I add a callback function to the button click event?

Answer №1

Your template file structure can be kept as it is, which looks good.

<button (click)="onClick()">
  <span *ngIf="!isLoading">
    ICON1
  </span>
  <span *ngIf="isLoading">
    ICON2
  </span>
</button>

For your typescript, initializing isLoading to false and then setting it to true in your onClick function before calling the async task is a simple approach. Once the task is completed, set it back to false.

public isLoading: boolean = false;
public onClick() {
  this.isLoading = true;
  this.service.taskAsync().subscribe(
    (data) => {
      this.isLoading = false;
      console.log("success");
    }, (error) => {
      this.isLoading = false;
      console.log("error");
    }
  );
}

To avoid code duplication, you can utilize a pipe as well.

public isLoading: boolean = false;
public onClick() {
  this.isLoading = true;
  this.service.taskAsync().pipe(
    finalize(() => {
      this.isLoading = false;
    })
  ).subscribe(
    (data) => {
      console.log("success");
    }, (error) => {
      console.log("error");
    }
  );
}

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

I'm curious about how to implement textarea functionality within Angular for modeling purposes

I have a desire to utilize the model and transmit it to the server. One instance of this is sending comments. comment.model.ts export interface Comment { article_no: number; username: string; nickname: string; creatat: Date; content: string; } ...

The type 'Promise<any>' cannot be assigned to the type 'Contact[]'

After exhausting all my resources on the internet and StackOverflow, I still couldn't find the right answer. This is my first project in Angular with MongoDB, but I keep encountering this error: "Type 'Promise' is not assignable to type &apo ...

Is it possible to use null and Infinity interchangeably in JavaScript?

I've declared a default options object with a max set to Infinity: let RANGE_DEFAULT_OPTIONS: any = { min: 0, max: Infinity }; console.log(RANGE_DEFAULT_OPTIONS); // {min: 0, max: null} Surprisingly, when the RANGE_DEFAULT_OPTIONS object is logged, i ...

Having Trouble with Imported JavaScript File in Astro

Why isn't the js file working in Astro when I try to import or add a source in the Astro file? For example: <script src="../scripts/local.js"></script> or <script>import '../scripts/local.js'</script> I am ...

Issue detected in the console: Angular and Express code linked with status code 200 displaying an error

I am attempting to delete data along with an image connected to that data via an image Id using a get route (since the delete route didn't work out for me). The data is successfully being deleted, but I keep receiving a 200 OK response followed by an ...

Why is the return type for the always true conditional not passing the type check in this scenario?

Upon examination, type B = { foo: string; bar: number; }; function get<F extends B, K extends keyof B>(f: F, k: K): F[K] { return f[k]; } It seems like a similar concept is expressed in a different way in the following code snippet: functi ...

Is it possible to dynamically close the parent modal based on input from the child component?

As I follow a tutorial, I am working on importing the stripe function from two js files. The goal is to display my stripe payment in a modal. However, I am unsure how to close the modal once I receive a successful payment message in the child. Below are s ...

Improve your code quality with TypeScript's type checking capabilities

I am currently utilizing TypeScript version 1.4.1 and I have a need to import an external module (specifically "chai") while ensuring type checking compatibility. Yet, I seem to be facing a naming conflict issue with the following code snippet: /// <r ...

How to handle an empty data response in Angular 2's HTTP service

My ASP.NET web API has a simple method with the following test results: $ curl localhost:5000/Api/GetAllQuestions [{"questionId":0,"value":"qqq","answers":[{"answerId":25,"value":"qwerty"}]}] However, I am encountering an issue in my Angular 2 HTTP serv ...

Arrange the angular datatables in a specific order without displaying the usual user interaction triangles

I am looking to arrange the data in a fixed manner without any user interaction for sorting. However, it seems that I can either completely disable ordering like this: this.dtOptions = { paging: false, lengthChange: false, searching: false, orderi ...

How to bring in a specific module using its name in TypeScript

Can a module in typescript import itself by its own name? For example, let's consider a module called my-module with various tests. Is it possible to import it within the tests using import ... from "my-module" instead of using a local path like impo ...

What is the best way to include text or a label on my Angular map without using a marker?

I am currently using the agm-map module in my angular project. I want to place a label or text at the center of a polygon on the map without using markers. How can I achieve this functionality in Typescript? I attempted to use the MapLabel Utility for thi ...

Encountering "Cannot write file" errors in VSCode after adding tsconfig exclude?

When I insert the exclude block into my tsconfig.json file like this: "exclude": ["angular-package-format-workspace"] I encounter the following errors in VSCode. These errors disappear once I remove the exclude block (However, the intended exclusion fu ...

Angular - Switching Displayed Information

I am currently working with Angular 4 and I am attempting to switch between contenteditable="true" and contenteditable="false" Here is what I have so far: <h1 (dblclick)="edit($event)" contentEditable="true">Double-click Here to edit</h1> Al ...

An issue occurred: TypeError - Unable to access the 'subscribe' property of an undefined object during a POST HTTP request in Angular [8]

I'm currently attempting to send data to a REST API using Postman. I am encountering an issue where I receive the error "Cannot read property 'subscribe' of undefined" when making a POST HTTP call, as shown in the console log: https://i.sta ...

When utilizing Angular 2, this message is triggered when a function is invoked from the Observable

One of my services is set up like this: @Injectable() export class DataService { constructor(protected url: string) { } private handleError(error: Response) { console.log(this.url); return Observable.throw(new AppError(error)); ...

The element is implicitly imparted with an 'any' type due to the incapability of utilizing an expression of type 'number' to index the type '{}'. This error occurs in the context of VUEJS

I have encountered an issue that I have been struggling to resolve despite trying numerous solutions. The problem arises while working on a project using Vue. Here is how I have structured my data: data(){ return{ nodes: {}, edges:{}, ...

Different Ways to Modify Data with the Change Event in Angular 8

How can I dynamically change data using the (change) event? I'm attempting to alter the gallery items based on a matching value. By default, I want to display all gallery items. public items = [{ value: 'All', name: 'All Item ...

Guide on translating text in Angular Material Snackbar using ngx translate

I have successfully integrated ngx translate into my project, allowing me to convert text on HTML pages into different languages using JSON files. However, I am facing a challenge in changing the language of the text displayed in the "Snackbar" component i ...

What is the significance of utilizing an empty value `[]` for a typed array interface instead of using an empty `{}` for a typed object interface?

Why can I initialize friends below as an empty array [], but not do the same for session with an empty object {}? Is there a way to use the empty object without needing to make all keys optional in the interface? const initialState: { friends: Array< ...