【jQuery】エラー『Uncaught TypeError: Cannot read properties of undefined (reading 'style')』の原因と解決方法

# エラー概要
- 以下のエラーが出て詰まってしまいました。jQueryのエラーっぽい。
- 本記事ではこちらの解決方法を記します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/65d27160-c08d-b30c-c489-747f5163c24c.png)

```
jquery.dataTables.js:5726 Uncaught TypeError: Cannot read properties of undefined (reading 'style')
    at _fnCalculateColumnWidths (jquery.dataTables.js:5726:20)
    at _fnInitialise (jquery.dataTables.js:4835:4)
    at Object.success (jquery.dataTables.js:1083:7)
    at i (jquery.min.js:2:27603)
    at Object.fireWith [as resolveWith] (jquery.min.js:2:28369)
    at A (jquery.min.js:4:13858)
    at XMLHttpRequest.<anonymous> (jquery.min.js:4:16146)
```

## 前提
- Djangoを利用して、以下のように規定していました。
- `common.js`で定義するカラムが、`home.html`のテーブルクラスに表示されるという仕様です。

```home.html
<table class="display nowrap" id="customer_table" style="width:100%">
    <thead>
        <tr>
            <th>会社名</th>
            <th>担当者名</th>
            <th>電話番号</th>
            <th>メールアドレス</th>
            <th>所在地</th>
            <th>担当部署</th>
            <th>担当者役職</th>
        </tr>
    </thead>
</table>
```

```common.js
'use strict';
$(document).ready(function() {
    var RenderTable = function(data) {
        var table = $('#customer_table').DataTable({
            "language": {
                "url": "//cdn.datatables.net/plug-ins/3cfcc339e89/i18n/Japanese.json"
            },
            "paging": true, // false to disable pagination (or any other option)
            "pagingType": "full_numbers",
            "pageLength": 10,
            "lengthMenu": [5, 10, 15, 75, 100],
            "deferRender": true,
            "dom": "lBfrtip",
            "buttons": [{
                "className": 'buttonsToHide invisible',
                "extend": 'csv',
                'exportOptions': {
                    columns: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
                },
            }],
            "order": [
                [0, "desc"]
            ],
            retrieve: true,
            data: data,
            columnDefs: [{
                "targets": [0],
                "orderable": false
            }],
            columns: [
                { "data": 'name' },
                { "data": 'pic' },
                { "data": 'phonenumber' },
                { "data": 'email' },
                { "data": 'location' },
                { "data": 'department' },
                { "data": 'position' },
                {
                    "data": "id",
                    "render": function(data, type, row, meta) {
                        return '<button type="button" class="btn btn-warning margin-8 js-show-edit-form" row=' + data + '>編集</button>';
                    }
                },
            ],
            columnDefs: [],
            "pageLength": 10,
        });
    };
```

- この状態でWebページ`home.html`を起動させると上述のエラーになってしまいます。
- エラーは、テーブルの列の幅を計算しようとしている際に、`style`プロパティが`undefined`となっていることを示しているようです。

# 解決方法
- 調べてみると、このエラーはだいたいの場合、カラムの数の不一致のケースが多いらしい。
    - [DataTables: Cannot read property style of undefined](https://stackoverflow.com/questions/39376658/datatables-cannot-read-property-style-of-undefined)

> The problem is that the number of `<th>` tags need to match the number of columns in the configuration (the array with the key "columns"). If there are fewer `<th>` tags than columns specified, you get this slightly cryptical error message.

- 以下のサイトにも同じように記載あり。
    - [jQuery DataTables: Common JavaScript console errors - TypeError: Cannot read property ‘style’ of undefined ](https://www.gyrocode.com/articles/jquery-datatables-common-javascript-console-errors/#typeerror-cannot-read-property-style-of-undefined)

> Number of th elements in the table header or footer differs from number of columns in the table body or defined using columns option.
Attribute colspan is used for th element in the table header.
Incorrect column index specified in columnDefs.targets option.

- でも「会社名」から「担当者役職」まであるしなぁ...ってよく見たら、「編集」ボタンの数まで入れると`data`（カラム）が8つあった。
- ということで、一番下に`<th></th>`を追加したら解決しました。。


```home.html
<table class="display nowrap" id="customer_table" style="width:100%">
    <thead>
        <tr>
            <th>会社名</th>
            <th>担当者名</th>
            <th>電話番号</th>
            <th>メールアドレス</th>
            <th>所在地</th>
            <th>担当部署</th>
            <th>担当者役職</th>
            <th></th>
        </tr>
    </thead>
</table>
```

# 原因
- 追加した`<th></th>`要素がない場合、テーブルのヘッダー行のセルの数が少なくなり、テーブルの列の定義と一致しなくなります。そのため、`jquery.dataTables.js`の`_fnCalculateColumnWidths`関数でエラーが発生していたのです。
- `columns`オプションで指定されたデータフィールドの数と、実際のテーブルのヘッダーセルの数が一致していなかったのです。
- `common.js`の`columns`オプションには、テーブルの列の定義が含まれており、`data`プロパティによって各列に表示するデータのフィールドを指定しているんですね。`data`プロパティが8つある場合は、テーブルのヘッダー行にも8つのセルが必要、ということです。