5
votes

Réinitialiser la table de données angulaire 6 montre this.dtElement undefined

J'ai créé un formulaire de sauvegarde et les données enregistrées seront affichées dans la table de données sur la même page. Datatable rerender () fonctionne très bien avec la soumission. mais lors de l'édition, rerender () affiche "this.dtElement" non défini.

manage-templates.component.ts

ERROR TypeError: "this.dtElement is undefined"

manage-templates.component.html

<div class="animated fadeIn">
    <div class="row">
        <div class="col-md-12">
            <div class="card">
                <div class="card-header">
                    <strong>Create Email Template</strong>
                </div>
                <form [formGroup]="createEmailTemplate" (ngSubmit)="onSubmit()" action="" method="post" class="form-horizontal">
                    <div class="card-body">
                        <div class="form-group row">
                            <label class="col-md-3 col-form-label" for="select1">Template Name</label>
                            <div class="col-md-6">
                                <input type="text" formControlName="templateName" class="form-control" placeholder="Template Name"
                                    [ngClass]="{ 'is-invalid': submitted && formfields.templateName.errors }">
                                <span class="invalid-feedback" *ngIf="formfields.templateName.errors">Please Enter
                                    Template Name</span>
                            </div>
                        </div>
                        <div class="form-group row">
                            <label class="col-md-3 col-form-label" for="select1">Template Description</label>
                            <div class="col-md-6">
                                <input type="text" formControlName="templateDesc" class="form-control" placeholder="Template Description"
                                    [ngClass]="{ 'is-invalid': submitted && formfields.templateDesc.errors }">
                                <span class="invalid-feedback" *ngIf="formfields.templateDesc.errors">Please Enter
                                    Template Description</span>
                            </div>
                        </div>
                        <div class="form-group row">
                            <label class="col-md-3 col-form-label" for="text-input">Email Body</label>
                            <div class="col-md-6">
                                <editor [(ngModel)]="dataModel" class="form-control" formControlName="templateBody"
                                    [ngClass]="{ 'is-invalid': submitted && formfields.templateBody.errors }"></editor>
                                <span class="invalid-feedback" *ngIf="formfields.templateBody.errors">Email body need
                                    not be empty</span>
                            </div>
                        </div>
                    </div>
                    <div class="card-footer">
                        <button type="submit" *ngIf="editFlag == false" class="btn btn-sm btn-primary" type="submit"><i class="fa fa-dot-circle-o"></i> Submit</button> &nbsp;
                        <button type="submit" *ngIf="editFlag == true" class="btn btn-sm btn-primary" type="submit"><i class="fa fa-dot-circle-o"></i> Update</button> &nbsp;
                        <button type="reset" class="btn btn-sm btn-danger" *ngIf="editFlag == false"><i class="fa fa-ban"></i> Reset</button>
                        <button type="reset" class="btn btn-sm btn-danger" *ngIf="editFlag == true" (click)="loadTemplates()"><i class="fa fa-ban"></i> Cancel</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <!--/.row-->
    <div class="row" *ngIf="editFlag == false">
        <div class="col-lg-12">
            <div class="card">
                <div class="card-header">
                    <i class="fa fa-align-justify"></i> Email Templates
                </div>
                <div class="card-body template_list">
                    <table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="row-border hover" width="100%">
                        <thead>
                            <tr>
                                <th>Template Name</th>
                                <th>Template Desc</th>
                                <th>Template Status</th>
                                <th>Actions</th>
                            </tr>
                        </thead>
                        <tbody *ngIf="templates?.length != 0">
                            <tr *ngFor="let template of templates">
                                <td>{{ template.template_name }}</td>
                                <td>{{ template.template_desc }}</td>
                                <!-- <td>{{ template.template_status }}</td> -->
                                <td>
                                    <span *ngIf="template.template_status == true" class="badge badge-success"> Active </span>
                                    <span *ngIf="template.template_status == false" class="badge badge-danger">Inactive</span>
                                </td>
                                <td>
                                    <a routerLink="edit" (click)="editTemplate(template.template_id)">Edit</a>
                                    &nbsp;/&nbsp;
                                    <a routerLink="disable/{{template.template_id}}" *ngIf="template.template_status == true">Deactivate</a>
                                    <a routerLink="enable/{{template.template_id}}" *ngIf="template.template_status == false">Activate</a>
                                </td> 
                            </tr>
                        </tbody>
                        <tbody *ngIf="templates?.length == 0">
                            <tr>
                                <td colspan="3" class="no-data-available">No data!</td>
                            </tr>
                        <tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>

lors de la modification d'un modèle d'e-mail pouvant être daté cache et les valeurs affichées dans le formulaire. Ici, je n'ai pas écrit de code pour les valeurs du formulaire de mise à jour. Je veux repeupler la page en appuyant sur le bouton "Annuler". Sur annuler le contenu du bouton dans la table de données se remplit sans pagination ni aucun style de table de données.

import { Component, OnInit, ViewEncapsulation, AfterViewInit, OnDestroy, ViewChild } from '@angular/core';
import { HttpClient, HttpResponse } from '@angular/common/http';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
import { NotifierService } from 'angular-notifier';
import { emailTemplatesService } from '../email-templates.service';
import { Globals } from '../../app.global';
import { Subject } from 'rxjs';
import { DataTableDirective } from 'angular-datatables';
import { Router } from '@angular/router';

class Template {
    template_id: string;
    template_name: string;
    template_desc: string;
    template_status: boolean;
}

class DataTablesResponse {
    data: any[];
    draw: number;
    recordsFiltered: number;
    recordsTotal: number;
}

@Component({
    selector: 'app-manage-templates',
    templateUrl: './manage-templates.component.html',
    styleUrls: ['./manage-templates.component.scss'],
    encapsulation: ViewEncapsulation.None
})

export class ManageTemplatesComponent implements AfterViewInit, OnDestroy, OnInit {

    // Creating formgroup object
    createEmailTemplate = new FormGroup({
        templateName: new FormControl('', [Validators.required]),
        templateBody: new FormControl('', [Validators.required]),
        templateDesc: new FormControl('', [Validators.required])
    });

    // Initializing variables
    submitted = false;
    editFlag = false;


    @ViewChild(DataTableDirective)
    dtElement: DataTableDirective;

    dtOptions: DataTables.Settings = {};

    dtTrigger: Subject<Template> = new Subject();
    templates: Template[];

    constructor(
        private http: HttpClient,
        private formBuilder: FormBuilder,
        private postData: emailTemplatesService,
        private notifier: NotifierService,
        private router: Router
    ) { }

    ngOnInit(): void {
        const that = this;
        this.dtOptions = {
            searching: false,
            pagingType: 'full_numbers',
            pageLength: 10,
            serverSide: true,
            processing: true,
            ajax: (dataTablesParameters: any, callback) => {
                that.http
                    .post<DataTablesResponse>(
                        Globals.baseAPIUrl + '/getEmailTemplates',
                        JSON.stringify({ dataTablesParameters })
                    ).subscribe(resp => {
                        that.templates = resp.data;
                        callback({
                            recordsTotal: resp.recordsTotal,
                            recordsFiltered: resp.recordsFiltered,
                            data: []
                        });
                    });
            },
            columns: [
                { title: 'Template Name', data: 'template_name' },
                { title: 'Template Desc', data: 'template_desc' },
                { title: 'Status', data: 'template_status' },
            ]
        };
    }

    ngAfterViewInit(): void {
        this.dtTrigger.next();
    }

    ngOnDestroy(): void {
        // Do not forget to unsubscribe the event
        this.dtTrigger.unsubscribe();
    }

    rerender(): void {
        this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
            // Destroy the table first
            dtInstance.destroy();
            // Call the dtTrigger to rerender again
            this.dtTrigger.next();
        });
    }

    get formfields() { return this.createEmailTemplate.controls; }

    // On form submit
    onSubmit() {
        this.submitted = true;

        if (this.createEmailTemplate.invalid) {
            return;
        }

        this.postData.createTemplate(JSON.stringify(this.createEmailTemplate.value)).subscribe(
            data => {
                this.notifier.notify(data['status'], data['message']);
                if (data['status'] === 'success') {
                    this.rerender();
                }
            }
        );
    }

    // On edit button
    editTemplate(template_id) {
        this.postData.getTemplateDetails(template_id).subscribe(
            data => {
                this.createEmailTemplate.patchValue({
                    templateName: data['message']['0']['templateName'],
                    templateDesc: data['message']['0']['templateDesc'],
                    templateBody: data['message']['0']['templateBody']
                });
                this.editFlag = true;
            }
        );
    }

    loadTemplates() {
        this.editFlag = false;
        this.rerender();
    }

}


3 commentaires

@AnoopSanker Avez-vous déjà trouvé la solution?


@YukwongTsang Pas vraiment. J'ai divisé le processus en deux composants, l'un pour l'enregistrement et l'autre pour l'édition / la mise à jour. Les deux utilisent le même fichier html. (Je sais que les solutions que j'ai appliquées ne sont pas une bonne façon)


@AnoopSanker Merci pour la réponse, j'ai l'impression de trouver la solution et cela peut vous aider aussi


3 Réponses :


0
votes

Voici ma solution, l'ordre de ViewChild / dtElement / ... est important dans ce cas

export class DemoComponent implements OnInit {

  @ViewChild(DataTableDirective)
  dtElement: DataTableDirective;
  dtOptions: any = {};
  dtInstance: DataTables.Api;
  dtTrigger: Subject<any> = new Subject();

  dt_data: any = {};
  ......

  ngOnInit() {
    this.dtOptions = {
     ...
   };
  }

  ngAfterViewInit(){
    //Define datatable 
    this.dtTrigger.next();
  }

  ngOnDestroy(): void {
    this.dtTrigger.unsubscribe();
  }

  SomeFunction(){
    //return the updated record, all the update function must be using rerender 
    this.dt_data = resp;
    this.rerender();
  }

  rerender(): void {
    try {
      this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
        // Destroy the table first
        dtInstance.destroy();
        // Call the dtTrigger to rerender again
        this.dtTrigger.next();
      });
    } catch (err) {
      console.log(err);
    }
  }


0 commentaires

0
votes

Si vous utilisez Forms et que chaque fois que vous soumettez de nouvelles données et données provenant de la demande de publication est différent, vous pouvez utiliser quelque chose comme ceci (angulaire 8) -

 export class Demo implements OnDestroy, OnInit, AfterViewInit {
   //this part did the job for me @view...
   @ViewChild(DataTableDirective, { static: false }) datatableElement: DataTableDirective;
  dtElement: DataTableDirective;
  dtOptions: any = {};
  dtInstance: DataTables.Api;
  dtTrigger: Subject<any> = new Subject();

  dt_data: any = {};
  ......

  ngOnInit() {
    this.dtOptions = {
     paging: false,
     "ordering": false,
     dom: 'Bfrtip',
     buttons: [
     'copy',
     'csv',
     'excel'
     ]
    };
  }

  ngAfterViewInit(){
    this.dtTrigger.next();
  }

  ngOnDestroy(): void {
    this.dtTrigger.unsubscribe();
  }

  getData(){
    //post request and when assigning data to variable
    this.dt_data = resp;
    this.rerender();
  }

  rerender(): void {
      //this.datatableElement is important
      this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
              dtInstance.destroy();
              this.dtTrigger.next();
            });

  }


0 commentaires

1
votes

Quand j'ai rencontré ce même problème, j'ai réussi à le résoudre en utilisant [hidden] au lieu de * ngIf. Apparemment, ViewChild n'a pas pu trouver le DataTableDirective car il n'était pas dans le HTML (grâce à * ngIf) entraînant l'erreur, car this.dtElement était égal à undefined.

Je vous suggère d'essayer d'utiliser ceci: p >

<div class="row" [hidden]="editFlag == true">
  <!-- DataTable Content -->
</div


0 commentaires