Unknown Parameter error during rows.add when multiple tables used.

Unknown Parameter error during rows.add when multiple tables used.

bobc02bobc02 Posts: 19Questions: 6Answers: 0

I am using SmartAdmin Angular 5 framework 1.9.1, which provides DataTables capabilities via a plugin. I have installed DataTables 1.10.18.

My app has several views, each view uses a table with different columns and data. When I start out, and visit any view with a table, all works fine. But, when I try to visit a different view, having different columns and data, I get an "unknown parameter" error.

I have traced the error to the rows.add function, that populates the tables during a table refresh function. The "unknown parameter" error is always for a column defined in the first table viewed. That column does not exist in subsequent views. I have studied the DataTables manual, and tried several fixes, such as table.clear, rows.remove. I even tried to redefine the columns using the correct definitions, right before the rows.add, but nothing helps.

You can login to my app.

To test, find Notifications on the left side, and go to General. Select a row, then click the Delete button. A confirmation will display. You can click No, that way I won't have to add more rows :-). This demonstrates that my table with custom buttons works. If Delete isn't working, logout and refresh browser, then try again.

To see the error message, go back to Notifications, and go to System.

If you go back to General, you'll see that the Delete button no longer works.

Here's some of the component.ts code for the sysMsg controller:

    import { NgModule, Component, OnInit, Injectable, Inject, ViewChild, DoCheck } from '@angular/core';
    import { FormGroup, FormControl } from '@angular/forms';

    import { FadeInTop } from "../shared/animations/fade-in-top.decorator";
    import { CookieService } from '../shared/cookies/cookie.service';
    import { NotificationsService } from './notifications.service';
    import { NotificationService } from '../shared/utils/notification.service';
    import { DatatableComponent } from '../shared/ui/datatable/datatable.component';
    import { environment } from '../../environments/environment.prod';

    declare let $:any;

    import { delay } from 'q';

    @FadeInTop()
    @Component({
      selector: 'sa-datatables-case',
      templateUrl: './notifsysmsg.component.html',
      styleUrls: ['../../assets/css/tmd_basic.css']
    })

    @Injectable()  
    export class NotifSysMsgComponent implements OnInit, DoCheck {
      @ViewChild('sysMsgTbl') sysMsgTbl: DatatableComponent;

      public sysMsgs = [];

      public useUTCTimestamps = 'NO';
      public archiveDaysStr = "30";

      constructor(
        private notificationsService: NotificationsService, //TMD version
        private notificationService: NotificationService,   //SA version used for dialogs
        private cookieService: CookieService,
      ) {}
    ...

   refreshDataTable() {
     console.log('NotifSysMsgComponent refreshDataTable - ENTRY');

     if($(this.sysMsgTbl)) {   
       if($(this.sysMsgTbl).DataTable) {
         console.log('NotifSysMsgComponent refreshDataTable - updating table');

         const sysMsgTbl = $($(this.sysMsgTbl).DataTable.tables()).DataTable();   
         sysMsgTbl.clear();
         sysMsgTbl.rows().remove();

         console.log('NotifSysMsgComponent refreshDataTable - *** error happens during add');
         sysMsgTbl.rows.add(this.notificationsService.sysMsgs);
         console.log('NotifSysMsgComponent refreshDataTable - *** end of add');

         sysMsgTbl.draw();
       }
     }
   }

Here's a table snippet from one of my views:

              <sa-datatable id="genMsgTbl"
                [options]="{
                  data: genMsgs,
                  columns: [
                     {data: 'checked'},
                     {data: 'rowid'},
                     {data: 'senderID'},
                     {data: 'message'},
                     {data: 'dateCreated'},
                     {data: 'dateExpires'}
                  ],
                  buttons: [
                    'copy', 'csv', 'pdf', 'print',
                    {
                        extend: 'selected',
                        text: 'Delete',
                        action: handleButtons()
                    },
                    {
                        extend: 'selected',
                        text: 'Archive',
                        action: handleButtons()
                    }
                  ],
                  columnDefs: [
                    {
                      targets: 0,
                      orderable: false,
                      className: 'select-checkbox'
                    },
                    {
                      targets: [2],
                      visible: true
                    }
                  ],
                  select: {
                      style: 'multiple',
                      selector: 'td:first-child'
                  },
                  order: [[ 1, 'asc']],
                  searching: true,
                  search: {
                      smart: false
                  }
                }"
                tableClass="table table-striped table-bordered table-hover"
              >
                <thead>
                <tr>
                  <th data-hide="mobile-p">Select</th>
                  <th data-hide="mobile-p">ID</th>
                  <th data-hide="mobile-p">Sender</th>
                  <th data-hide="mobile-p">Message</th>
                  <th data-hide="mobile-p">Date Sent</th>
                  <th data-hide="mobile-p">Date Expires</th>
                </tr>
                </thead>
              </sa-datatable>

And, here's a snippet from a second view:

              <sa-datatable id="sysMsgTbl"
                [options]="{
                  data: sysMsgs,
                  columns: [
                     {data: 'senderID'},
                     {data: 'message'},
                     {data: 'dateCreated'},
                     {data: 'dateExpires'}
                  ],
                  buttons: [
                    'copy', 'csv', 'pdf', 'print'
                  ],
                  columnDefs: [ 
                    {
                      targets: [2],
                      visible: true
                    }
                  ],
                  order: [[ 1, 'asc']],
                  searching: true,
                  search: {
                      smart: false                  
                  }               
                }"
                tableClass="table table-striped table-bordered table-hover"
              >
                <thead>
                <tr>
                  <th data-hide="mobile-p">Sender</th> 
                  <th data-hide="mobile-p">Message</th>
                  <th data-hide="mobile-p">Date Sent</th>
                  <th data-hide="mobile-p">Date Expires</th>
                </tr>
                </thead>
              </sa-datatable>

I certainly appreciate any help offered!

Bob

Answers

  • colincolin Posts: 15,118Questions: 1Answers: 2,583

    Hi @bobc02 ,

    I couldn't log in to your app, it's after a user/pass. But, I suspect the code is trying to use the previous table initialisation - you could use destroy as part of the initialisation to ensure it's starting fresh.

    Hope that helps,

    Cheers,

    Colin

  • kthorngrenkthorngren Posts: 20,150Questions: 26Answers: 4,736
    edited March 2019

    If the problem happens with rows.add() then that would suggest the data structure you are adding doesn't match the structure of the Datatable. This is the line in question:

    sysMsgTbl.rows.add(this.notificationsService.sysMsgs);

    Use console.log(this.notificationsService.sysMsgs); to see what the data is. Using rows.add() expects multiple rows to be added and that the data is in an array. If you are adding one row and its not in an array then you would use row.add().

    Kevin

  • bobc02bobc02 Posts: 19Questions: 6Answers: 0

    Regarding login, I'm sorry, I forgot to unlock the account. Please try again.

    I tried the destroy option, but, as you can see from the two View sources, I define some custom features that I do not know how to reconstruct from the component.ts code.

    I do realize the problem is due to the data structure being applied to the wrong table definition. That's the puzzling part. At the point of error, I am in the second component.ts (sysMsgs is its data structure), which is different from the first component.ts (which uses genMsgs). I think I need to figure out how to "replace" the table definition in the refreshDataTable() of the SysMsgs component.

    I appreciate your help! Hopefully, a solution can be developed.

    Bob

  • bobc02bobc02 Posts: 19Questions: 6Answers: 0

    Problem solved.

    As Colin said, adding a table destroy was the key. I had tried it before, but it was within the second component, right before I did the rows.add - wrong place!. I got to thinking about it, and added an event listener in the first component, so that when the component was ending, it would destroy the table.

    Here's some of the code:

       ngOnInit() {          
         this.navigationSubscription = this.router.events.subscribe((e: any) => {
           if (e instanceof NavigationEnd) {
             this.destroyTable();
           }
         });
    ...
    
    
       destroyTable() {         
         if($(this.sysMsgTbl)) {   
           if($(this.sysMsgTbl).DataTable) {
    
             const sysMsgTbl = $($(this.sysMsgTbl).DataTable.tables()).DataTable();   
             sysMsgTbl.clear();
             sysMsgTbl.destroy();
           }
         }       
       }
    

    I put the updated coded on the server so that you can try it.

    There are some issues with webservice syncing, and custom button selections not always working, but the primary issue of changing views, and the tables, seems to be fixed.

    Thanks for your help!

    Bob

This discussion has been closed.