2017-06-16 6 views
2

これは難しいですが、私はできる限り自分自身を説明しようとします。角度 - データ型:TypeError:ヌルのプロパティ 'nodeName'を読み取ることができません

簡単な説明:私は数ヶ月前にプロジェクトのテーマを購入したので、

私は私の角のプロジェクトに統合DataTableのライブラリを持っているが、それを持っていました。 Themeが更新されたので、私は最新バージョンのプロジェクトを更新しました。

奇妙なことは、動作していないのがDataTableで、DataTableが変更されていないことです。

コードの内訳:Xコンポーネントから

私は私の共有サービスIBOsServiceの方法をトリガしています。

このメソッドがトリガーされると、私のDatatableComponentは、Promiseのdatatablesライブラリをインポートします。

今までこれまで問題はありませんでした。 DatatableComponent

this.tablesService.initTableData$.subscribe(() => { 
       if (!this.datatableInitialized) { 
        log.info('Starting script import promise'); 

        Promise.all([ 
         System.import('script-loader!my-plugins/datatables-bundle/datatables.min.js') 
        ]).then(values => { 
         log.data('success', JSON.stringify(values)); 
         this.render(); 
        }, reason => { 
         log.error('error', JSON.stringify(reason)); 
        }); 
       } 
      } 
     ); 

私のコンソールでは、私が見る:DataTables success [{}]。したがって、私は約束が成功したことを理解しています。

したがって、this.render();メソッドを入力します。

方法はこちらこのラインまでに行く:

const _dataTable = element.DataTable(options); 

事は、私はそれゆえ、私のIDEで、私はなど、すべての変数、メソッド、にナビゲートすることができます...しかし、私はDataTable()にナビゲートすることができないということです推測はこのメソッドを認識していないため、エラーをスローします。

しかしスクリプトが約束にロードされると、IDEは、DataTableのメソッドのマッピングを持っていないこと、正常である...

全コンポーネントコード:

import { Component, Input, ElementRef, AfterContentInit, OnInit, Injectable, OnDestroy } from '@angular/core'; 
import { IBOsService } from '../../../+ibos/ibos.service'; 
import { Subscription } from 'rxjs/Subscription'; 
import { Log, Level } from 'ng2-logger'; 
import { logConfig } from '../../../../environments/log_config'; 

const log = Log.create('DataTables'); 
log.color = logConfig.dataTable; 

declare let $: any; 

@Component({ 

    selector: 'sa-datatable', 
    template: ` 
     <table class="dataTable {{tableClass}}" width="{{width}}"> 
      <ng-content></ng-content> 
     </table> 
    `, 
    styles: [ 
     require('my-plugins/datatables-bundle/datatables.min.css') 
    ] 
}) 
@Injectable() 
export class DatatableComponent implements OnInit, OnDestroy { 

    @Input() public options: any; 
    @Input() public filter: any; 
    @Input() public detailsFormat: any; 

    @Input() public paginationLength: boolean; 
    @Input() public columnsHide: boolean; 
    @Input() public tableClass: string; 
    @Input() public width = '100%'; 

    public datatableInitialized: boolean; 

    public subscription: Subscription; 

    constructor(private el: ElementRef, private tablesService: IBOsService) { 
     this.tablesService.refreshTable$.subscribe((tableParams) => { 
       this.filterData(tableParams); 
      } 
     ); 

     this.tablesService.initTableData$.subscribe(() => { 
       if (!this.datatableInitialized) { 
        log.info('Starting script import promise'); 

        Promise.all([ 
         System.import('script-loader!my-plugins/datatables-bundle/datatables.min.js') 
        ]).then(values => { 
         log.data('success', JSON.stringify(values)); 
         this.render(); 
        }, reason => { 
         log.error('error', JSON.stringify(reason)); 
        }); 
       } 
      } 
     ); 
    } 

    ngOnInit() { 
    } 

    render() { 
     log.info('Starting render!'); 

     const element = $(this.el.nativeElement.children[0]); 
     let options = this.options || {}; 

     log.info('1 render!'); 

     let toolbar = ''; 
     if (options.buttons) { 
      toolbar += 'B'; 
     } 
     log.info('2 render!'); 

     if (this.paginationLength) { 
      toolbar += 'l'; 
     } 

     if (this.columnsHide) { 
      toolbar += 'C'; 
     } 

     log.info('3 render!'); 

     if (typeof options.ajax === 'string') { 
      const url = options.ajax; 
      options.ajax = { 
       url: url, 
       // complete: function (xhr) { 
       // 
       // } 
      }; 
     } 

     log.info('4 render!'); 

     options = $.extend(options, { 

      'dom': '<\'dt-toolbar\'<\'col-xs-12 col-sm-6\'f><\'col-sm-6 col-xs-12 hidden-xs text-right\'' + toolbar + '>r>' + 
      't' + 
      '<\'dt-toolbar-footer\'<\'col-sm-6 col-xs-12 hidden-xs\'i><\'col-xs-12 col-sm-6\'p>>', 
      oLanguage: { 
       'sSearch': `<span class='input-group-addon'><i class='glyphicon glyphicon-search'></i></span>`, 
       'sLengthMenu': '_MENU_' 
      }, 
      'autoWidth': false, 
      retrieve: true, 
      responsive: true, 
      initComplete: (settings, json) => { 
       element.parent() 
        .find('.input-sm') 
        .removeClass('input-sm') 
        .addClass('input-md'); 
      } 
     }); 

     log.info('5 render! element', JSON.stringify(element)); 
     log.info('5.1 render! options', JSON.stringify(options)); 

     const _dataTable = element.DataTable(options); 

     log.info('5.2 render! _dataTable', JSON.stringify(_dataTable)); 

     if (this.filter) { 
      // Apply the filter 
      element.on('keyup change', 'thead th input[type=text]', function() { 
       console.log('searching?'); 
       _dataTable 
        .column($(this).parent().index() + ':visible') 
        .search(this.value) 
        .draw(); 
      }); 
     } 

     log.info('6 render!'); 

     if (!toolbar) { 
      element.parent().find('.dt-toolbar') 
       .append(
        '<div class="text-right">' + 
        '<img src="assets/img/logo.png" alt="SmartAdmin" style="width: 111px; margin-top: 3px; margin-right: 10px;">' + 
        '</div>' 
       ); 
     } 

     log.info('7 render!'); 

     if (this.detailsFormat) { 
      const format = this.detailsFormat; 
      element.on('click', 'td.details-control', function() { 
       const tr = $(this).closest('tr'); 
       const row = _dataTable.row(tr); 
       if (row.child.isShown()) { 
        row.child.hide(); 
        tr.removeClass('shown'); 
       } else { 
        row.child(format(row.data())).show(); 
        tr.addClass('shown'); 
       } 
      }); 
     } 

     log.info('8 render!'); 

     this.datatableInitialized = true; 
    } 

    filterData(tableParams) { 
     console.log('reloading DT... With these parameters: ' + JSON.stringify(tableParams)); 

     const element = $(this.el.nativeElement.children[0]); 
     const table = element.find('table.dataTable'); 

     log.data('current table element is: ', JSON.stringify(table)); 

     Object.keys(tableParams).forEach(function (key) { 
      log.warn('current key: ', JSON.stringify(key)); 
      table.DataTable().column(`${key}:name`).visible(tableParams[key]); 
     }); 

     table.DataTable().ajax.reload(); 
    } 

    ngOnDestroy() { 
     if (this.subscription) { 
      this.subscription.unsubscribe(); 
     } 
    } 
} 

私はログを使ってコンポーネントに侵入したことがわかります。コンポーネントがどこで失敗したかを理解するのに役立ちました。

全コンソールログ:

enter image description here

興味深い情報:私はfilterData(tableParams)メソッドを呼び出す場合

... DataTableには問題なくレンダリングします。

これは私に2つのことを伝えます:

  1. DataTable()は問題ではありません。
  2. 問題は初回レンダリング時にのみであり、更新すると問題は発生しません。

私は、テキストの私のウォール用ひどく残念...しかし、私は私自身のことで、いくつかのシャーロック・ホームズを行なったし、解決策を見つけることができませんでした。

説明が必要な場合や詳細がわかっている場合は、

ありがとうございます!

更新:日のデバッグの後、私はエラーの可能性のあるソースを発見した

enter image description here

事がsnullであるということです。

多分DataTableで経験したことがある人や、この問題が発生した人は、何が起こっているのかを知ることができます。

私は...デバッグここになります。)

アップデート2:私は、DataTableのはが最初のAjax呼び出しを行っていないことが判明よりデバッグした後

を。

POSTでAjaxコールを使用して、サーバー側のDataTablesを使用しています。ここで

optionsオブジェクトのコードされています

this.options = { 
    dom: 'Bfrtip', 
    processing: true, 
    serverSide: true, 
    pageLength: 20, 
    searchDelay: 1200, 
    ajax: { 
     url: this.jsonApiService.buildURL('/test_getUsers.php', 'remote'), 
     type: 'POST', 
     data: function (d) { 
      Object.assign(d, IBOsTable.params); 
      log.data('DT options obj. New params are: ', JSON.stringify(IBOsTable.params)); 
      return d; 
     } 
    }, 
    columns: this.initColumns, 
}; 

このは、初期化にAjax呼び出しを行っていませんが、それはtable.DataTable().ajax.reload();にそれを作っています。

これは、コードは(魔法のようにreload()作品に)正しくないか、壊れていないことを私に告げる...

本のDataTableの初期化が機能しない理由私はまだ完全にはundesrtandingていないよ...しかし、私は十分に近いと信じています!

+0

が定義Sで?私はそのコードが表示されません – Bindrid

+0

@Bindridこんにちは! 's'は決定的ではありません。 DTが最初のAjaxコールを作成していないことがわかったので、レンダリングする実際のデータがないため、エラーが発生します。ここで問題となっているのは、最初のAjaxコールを作成していない理由です。乾杯! ;) – SrAxi

答えて

0

私は最終的にエラーの原因を見つけました!あなたは私のアップデートを読めば

あなたは私のDataTableが最初のAjax呼び出しを行っていなかったことを考え出していますが、reload()に完璧に働いていた:初期化中にJavaScriptエラーがなかったためでした

Ajax呼び出しを行うことができます。ヒント:TypeError:nullのプロパティ 'nodeName'を読み取ることができません

speaking to Allan (from DataTables)の後、theadの列の数がtbodyの列の数と等しくないためにエラーが発生する可能性があるというヒントを教えてくれました。

私は自分の.htmlを確認しましたが、空きがありました。<thead><tfoot>というタグがありました。私は彼らにコメントした...そして働いた!角度2内

  • 依存
  • のjQueryライブラリのApp
  • のDataTableサーバ側
  • をインスタンス化の
  • 多くの異なる方法:私は駆け寄ると、すべての可能な解決策を超えるいる

    enter image description here

    コードでのアプローチの変更:TypeScript、jQuery、Ng2など...

最後に、この問題を回避するためにDataTableがロードされていたdivをクリアするだけでした。

楽しい事実を:その私のアプリは今まで、問題なく3/4ヶ月間のDataTableと何の問題も働いていない.htmlのでは...

関連する問題