質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

937閲覧

【JS】 入れ子になったクラスのメソッドの呼び出し方法がわかりません.

ymymymymy

総合スコア9

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2022/12/04 03:31

【JS】 入れ子になったクラスのメソッドの呼び出し方法がわかりません.

イメージ説明

↑ 後から行を追加できるエディタをtable要素を用いて作っています.

実現したいこと

「+」ボタンが押されたら,その直下に新しく行(tr要素以下)を追加したい.

問題点

現状はTdクラスでクリックイベントの処理を記述していて,Tdクラスから新しく行を追加するTableクラスの "setNewOneLine" メソッドをどう呼び出せばいいのかがわかりません.


下記にコードの全文を記述しています.

js

1// main.js 2 3const FLOAT_SUB = (num1, num2) => Number((num1 - num2).toFixed(2)); 4 5class Table { 6 constructor(row) { 7 this.TABLE_ELEM = document.createElement('table'); 8 this.TBODY_ELEM = document.createElement('tbody'); 9 this.row = row; // 行数 10 this.tableArray = new Array(); // tbodyの中身 "tr" を保持 11 12 this._setTable(); 13 } 14 15 get table() { 16 return this.TABLE_ELEM; 17 } 18 19 _setTable() { 20 21 for(let i = 1; i <= this.row; i++) { 22 this.TBODY_ELEM.appendChild(this.createOneLine(i)); 23 } 24 25 this.TABLE_ELEM.appendChild(this.TBODY_ELEM); 26 } 27 28 createOneLine(num) { 29 let trElem = document.createElement('tr'); 30 let index = FLOAT_SUB(num, 1); 31 let th = new Th(index, num); 32 let text = new Td(index, "Text is written here.", "input"); 33 let func = new Td(index, "+", "button"); 34 trElem.appendChild(th.thElem); 35 trElem.appendChild(text.tdElem); 36 trElem.appendChild(func.tdElem); 37 38 this.tableArray[index] = trElem; 39 return trElem; 40 } 41 42 /** 43 * 新しく行を追加する 44 * @param {Number} num tableArray に新しく追加する要素番号-1 45 */ 46 setNewOneLine(num) { 47 this.tableArray[FLOAT_SUB(num, 1.1)].after(this.createOneLine(num)); 48 this.row++; 49 } 50} 51 52/** 53 * td エレメントの作成 54 * @param {Number} index TableクラスのtableArrayの要素番号 55 * @param {String} text tdの子要素のテキスト 56 * @param {String} childTag tdの子要素のタグネーム 57 * @returns 裏返すコマの座標と裏返すコマの数 58 */ 59class Td { 60 constructor(index, text, childTag) { 61 this.index = index; 62 this.tdElem = document.createElement('td'); 63 this.text = text; 64 this.childTag = childTag; 65 66 this._setTd() 67 } 68 69 _setTd() { 70 if(this.childTag == "button") { 71 this.createBtnElem(); 72 } else { 73 this.createInputElem(); 74 } 75 } 76 77 createInputElem() { // inputをtdElementの子要素として追加 78 let inputElem = document.createElement('input'); 79 inputElem.type = this.text; 80 inputElem.value = this.text; 81 this.tdElem.appendChild(inputElem); 82 } 83 createBtnElem() { // ボタンをtdElementの子要素として追加 84 let btnElem = document.createElement('button'); 85 btnElem.type = "button"; 86 btnElem.innerText = this.text; 87 88 btnElem.addEventListener('click', () => { 89 console.log("btn click."); 90 91 // ここに新しく行を追加する処理を書きたい. 92 93 }); 94 95 this.tdElem.appendChild(btnElem); 96 } 97} 98 99class Th { 100 constructor(index, text) { 101 this.index = index; 102 this.thElem = document.createElement('th'); 103 this.text = text; 104 105 this._setTh(); 106 } 107 108 _setTh() { 109 this.thElem.innerText = this.text; 110 } 111} 112 113 114window.onload = () => { 115 let table = new Table(3); 116 document.getElementById('hoge').appendChild(table.table); 117 118 table.setNewOneLine(1.1); // 1行目の+が押されたと仮定 119 table.setNewOneLine(1.2); // 1.1行目の+が押されたと仮定 120 console.log(table); 121}

html

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>hoge</title> 7 <script src="./js/main.js"></script> 8</head> 9<body> 10 <main role="main"> 11 <div id="hoge"> 12 </div> 13 </main> 14</body> 15</html>

質問

  • Tableクラスの中で宣言されたTdクラスから,Tableクラスのメソッドを呼び出す方法について
  • このクラス設計では呼び出せないのであれば,どうすれば良いか最適解を教えていただきたい

以上,よろしくお願い致します.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

qnoirさまの回答のようにTableインスタンスを渡しておくのが最も変更が少ないかと思います。

別案1: イベント委譲
ボタンにイベントを付けるのではなく、Table クラスが this.TABLE_ELEM.addEventListener('click', e => ...) してイベントを処理します。どのボタンが押されたかわかるように、ボタンに data-index 属性でも付けて index 値がわかるようにしておきましょう。

別案1: カスタム要素
Table クラスをカスタム要素にすれば、要素をクラスのインスタンスとして扱えるので event.target.closest('my-table') などで簡単に Table インスタンスが得られます。
残念ながらSafariではカスタマイズされた組み込み要素が非対応なので、自律カスタム要素display: table などを指定する必要があります。

投稿2022/12/04 15:20

int32_t

総合スコア20884

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

Tableクラスの中で宣言されたTdクラスから,Tableクラスのメソッドを呼び出す方法

変更を最小限にするならば、下記のようにすればよいのではないでしょうか。

  • Table 内でTd (ボタン)を生成するときに、自分自身のインスタンスを渡すようにする。

diff

1 2class Table { 34 createOneLine(num) { 5 6- let func = new Td(index, "+", "button"); 7+ let func = new Td(index, "+", "button", this); 8 略 9 }
  • Td のコンストラクタで、table のインスタンスを受け取るようにしておく。

diff

1 class Td { 2- constructor(index, text, childTag) { 3+ constructor(index, text, childTag, table) { 4 this.index = index; 5 this.tdElem = document.createElement('td'); 6 this.text = text; 7 this.childTag = childTag; 8+ this.parentTable = table; 9 this._setTd() 10 }
  • ボタンをクリックしたら、table の setNewOneLine メソッドを呼び出す。

diff

1class Td { 23 createBtnElem() { // ボタンをtdElementの子要素として追加 45 btnElem.addEventListener('click', () => { 6 // ここに新しく行を追加する処理を書きたい. 7+ this.parentTable.setNewOneLine((this.index + 1.1).toFixed(1)) 8 }); 9 10 this.tdElem.appendChild(btnElem); 11 }

修正後のコード全体:

js

1 // main.js 2 3 const FLOAT_SUB = (num1, num2) => Number((num1 - num2).toFixed(2)); 4 5 class Table { 6 constructor(row) { 7 this.TABLE_ELEM = document.createElement('table'); 8 this.TBODY_ELEM = document.createElement('tbody'); 9 this.row = row; // 行数 10 this.tableArray = new Array(); // tbodyの中身 "tr" を保持 11 this._setTable(); 12 } 13 14 get table() { 15 return this.TABLE_ELEM; 16 } 17 18 _setTable() { 19 20 for (let i = 1; i <= this.row; i++) { 21 this.TBODY_ELEM.appendChild(this.createOneLine(i)); 22 } 23 24 this.TABLE_ELEM.appendChild(this.TBODY_ELEM); 25 } 26 27 createOneLine(num) { 28 let trElem = document.createElement('tr'); 29 let index = FLOAT_SUB(num, 1); 30 let th = new Th(index, num); 31 let text = new Td(index, "Text is written here.", "input"); 32 let func = new Td(index, "+", "button", this); 33 trElem.appendChild(th.thElem); 34 trElem.appendChild(text.tdElem); 35 trElem.appendChild(func.tdElem); 36 37 this.tableArray[index] = trElem; 38 return trElem; 39 } 40 41 /** 42 * 新しく行を追加する 43 * @param {Number} num tableArray に新しく追加する要素番号-1 44 */ 45 setNewOneLine(num) { 46 this.tableArray[FLOAT_SUB(num, 1.1)].after(this.createOneLine(num)); 47 this.row++; 48 } 49 } 50 51 /** 52 * td エレメントの作成 53 * @param {Number} index TableクラスのtableArrayの要素番号 54 * @param {String} text tdの子要素のテキスト 55 * @param {String} childTag tdの子要素のタグネーム 56 * @returns 裏返すコマの座標と裏返すコマの数 57 */ 58 class Td { 59 constructor(index, text, childTag, table) { 60 this.index = index; 61 this.tdElem = document.createElement('td'); 62 this.text = text; 63 this.childTag = childTag; 64 this.parentTable = table; 65 this._setTd() 66 } 67 68 _setTd() { 69 if (this.childTag == "button") { 70 this.createBtnElem(); 71 } else { 72 this.createInputElem(); 73 } 74 } 75 76 createInputElem() { // inputをtdElementの子要素として追加 77 let inputElem = document.createElement('input'); 78 inputElem.type = this.text; 79 inputElem.value = this.text; 80 this.tdElem.appendChild(inputElem); 81 } 82 createBtnElem() { // ボタンをtdElementの子要素として追加 83 let btnElem = document.createElement('button'); 84 btnElem.type = "button"; 85 btnElem.innerText = this.text; 86 87 btnElem.addEventListener('click', () => { 88 // ここに新しく行を追加する処理を書きたい. 89 this.parentTable.setNewOneLine((this.index + 1.1).toFixed(1)) 90 }); 91 92 this.tdElem.appendChild(btnElem); 93 } 94 } 95 96 class Th { 97 constructor(index, text) { 98 this.index = index; 99 this.thElem = document.createElement('th'); 100 this.text = text; 101 this._setTh(); 102 } 103 104 _setTh() { 105 this.thElem.innerText = this.text; 106 } 107 } 108 109 110 window.onload = () => { 111 let table = new Table(3); 112 document.getElementById('hoge').appendChild(table.table); 113 114 table.setNewOneLine(1.1); // 1行目の+が押されたと仮定 115 table.setNewOneLine(1.2); // 1.1行目の+が押されたと仮定 116 } 117

投稿2022/12/04 04:29

編集2022/12/05 11:04
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問