Home > front end >  The Renderer2, in ngAfterViewInit is beeing called the same number of times that I have left the pag
The Renderer2, in ngAfterViewInit is beeing called the same number of times that I have left the pag

Time:04-26

I have a angular component that uses ngAfterViewInit the first time I am on the page that uses the component and I click the button the ngAfterViewInit calls the method this.updateListSecondTable() once. When I leave the page and comme back the ngAfterViewInit calls the method this.updateListSecondTable() twice when I leave and come back a third time it calls the method tree times and so on why is this the case? Thank you for your help.

export class PurchaseReceptionsComponent implements OnInit, OnDestroy  {
  dtOptionsPurchaseReceptions: DataTables.Settings = {};
  dtOptionsReceptionsConfirmed: DataTables.Settings = {};

  public selectAll: boolean = false;

  public lstPurchases: number[] = [];
  public lstPurchasesRecived: number[] = [];

  constructor(private renderer: Renderer2,
    private router: Router,
    private toastr: ToastrService,
    private http: HttpClient,
    private translate: TranslateService,
    private purchaseService: PurchaseService) { }

  ngOnInit(): void {

    var token = localStorage.getItem("token");

    this.dtOptionsPurchaseReceptions = {
      ajax: {
        url: this.purchaseService.getPurchasesRecptionsForDatatable(),
        type: "GET",
        dataType: "json",
        headers: { "Authorization": "Bearer "   token }
      },
      columns: [
        {
          render: function (data: any, type: any, row: any) {
            return '<input type="checkbox" name = "purchasecheck" id="move-purchase-id'   row.PurchaseId   '" move-purchase-id="'   row.PurchaseId   '" value="'   row.PurchaseId   '" >';
          }
        },
        {
          data: 'Supplier.Name'
        },
        {
          render: function (data: any, type: any, row: any) {
            if (row.Contract != undefined) {
              return '<a href="/contract/'   row.Contract.ContractNumber   '/search" target="_blank">'   row.Contract.ContractNumber   '</a>';
            }
            return '';
          }
        },
        {
          data: 'OrderNumber'
        },
        {
          data: 'SupplierOrderNumber'
        },
        {
          data: 'Component.Brand'
        },
        {
          data: 'Component.Designation'
        },
        {
          data: 'Component.Type'
        },
        {
          data: 'Component.Reference'
        },
        {
          data: 'Term'
        },
        {
          data: 'OrderQuantity'
        },
        {
          data: 'DeliveredQuantity'
        },
        {
          data: 'UnitPrice'
        },
        {
          data: 'OrderQuantity'
        },
      ],
      destroy: true,
      pagingType: 'full_numbers',
      pageLength: 10,
      order: [[1, 'asc']],
      columnDefs: [{
        defaultContent: '',
        targets: [0],
        searchable: false,
        orderable: false,
        className: 'no-marking',
        width: "25px"
      },
      {
        defaultContent: '',
        targets: [2]
      }]
    };

    this.dtOptionsReceptionsConfirmed = {
      destroy: true,
      pagingType: 'full_numbers',
      pageLength: 10,
      columnDefs: [{
        defaultContent: '',
        targets: [1]
      }]        
    };

    this.getAllPurchaseReceptionsId();
  }

  ngOnDestroy() {
    this.lstPurchases = [];
    this.lstPurchasesRecived = [];
    this.selectAll = false;

    this.dtOptionsPurchaseReceptions = {}
    this.dtOptionsReceptionsConfirmed = {}
  }

  ngAfterViewInit(): void {
    this.renderer.listen('document', 'click', (event) => {
      if (event.target.hasAttribute("move-purchase-id")) {
        var purchaseIdNotFormated: string = event.target.getAttribute("move-purchase-id");
        var purchaseId: number = Number(purchaseIdNotFormated.replace("move-purchase-id", ""));
        this.updateListSecondTable(purchaseId);
      }
    });
  }
}

CodePudding user response:

The description of this issue is textbook memory leak. You should make sure you don't leave references to this component hanging around and preventing it from being properly destroyed and cleaned up. My advice is to start handling the renderer.listen thing more carefully.

Looking at the docs, it seems that it returns An "unlisten" function for disposing of this handler.

This means that you can capture the return value of the listen call and keep it around to dispose of the handler inside onDestroy:

export class PurchaseReceptionsComponent implements OnInit, OnDestroy  {
  // ... 
  private unlisten: (() => void) | null = null;

  ngAfterViewInit(): void {
    this.unlisten = this.renderer.listen('document', 'click', (event) => {
      // ...
    });
  }

  ngOnDestroy() {
    // ...
    this.unlisten?.();
  }
}
  • Related