innerHTMLプロパティに文字列を足しこむと、意図した表示にならない。 - JavaScript
innerHtmlプロパティに文字列を足しこむと、意図した表示にならない現象の紹介と対処法を紹介します。
現象の確認
以下のHTMLファイルを作成します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
table {
border-collapse: collapse;
border: 1px solid #717171;
}
table tr td {
padding: 0.1rem 1rem 0.1rem 0.5rem;
border: 1px solid #717171;
}
</style>
<script type="text/javascript">
window.onload = proc;
function proc() {
var header = ["ID","品名","価格","在庫数"];
var item = [
[1, "ぺんぎんクッキー", 340, 8],
[2, "しろくまアイス", 240, 12],
[3, "かるがもサブレ", 140, 6],
[4, "ふくろうカステラ", 680, 3]
]
var elem = document.getElementById("output");
elem.innerHTML = "<table><thead>"
elem.innerHTML += "<tr>";
for (i = 0; i < header.length; i++) {
elem.innerHTML += "<th>" + String(header[i]) + "</th>";
}
elem.innerHTML += "</tr></thead><tbody>";
for (i = 0; i < item.length; i++) {
elem.innerHTML += "<tr>";
for (j = 0; j < item[i].length; j++) {
elem.innerHTML += "<td>" + String(item[i][j]) + "</td>";
}
elem.innerHTML += "</tr>";
}
elem.innerHTML += "</tbody></table>";
}
</script>
</head>
<body>
<h2>innerHtmlがうまく動作しないデモ</h2>
<div id="output"></div>
</body>
</html>
解説
ページ読み込み時に
proc
関数を実行します。
ページ表示時のJavaScriptの実行の詳細は
こちらの記事を参照してください。
window.onload = proc;
ヘッダの配列と、コンテンツの2次元配列を作成します。
var header = ["ID","品名","価格","在庫数"];
var item = [
[1, "ぺんぎんクッキー", 340, 8],
[2, "しろくまアイス", 240, 12],
[3, "かるがもサブレ", 140, 6],
[4, "ふくろうカステラ", 680, 3]
];
getElementByIdメソッドを呼び出し、id="output" のDOM要素を取得します。
var elem = document.getElementById("output");
取得した要素のinnerHTMLプロパティに出力したいタグの文字列を足しこんでいきます。
tableタグを出力して、ヘッダの値とコンテンツを表組してページに表示します。
elem.innerHTML = "<table><thead>"
elem.innerHTML += "<tr>";
for (i = 0; i < header.length; i++) {
elem.innerHTML += "<th>" + String(header[i]) + "</th>";
}
elem.innerHTML += "</tr></thead><tbody>";
for (i = 0; i < item.length; i++) {
elem.innerHTML += "<tr>";
for (j = 0; j < item[i].length; j++) {
elem.innerHTML += "<td>" + String(item[i][j]) + "</td>";
}
elem.innerHTML += "</tr>";
}
elem.innerHTML += "</tbody></table>";
表示結果
上記のHTMLファイルをWebブラウザで開きます。下図のページが表示されます。
tableタグを出力しているロジックですが、コンテンツが表組されません。
bodyのタグ構造は以下になります。trタグやtdタグが無くなっています。
<body>
<h2>innerHtmlがうまく動作しないデモ</h2>
<div id="output"><table><thead></thead></table>ID品名価格在庫数1ぺんぎんクッキー34082しろくまアイス240123かるがもサブレ14064ふくろうカステラ6803</div>
</body>
原因
innerHTMLプロパティに値を順次代入した場合、代入した直後にタグの整合性の検証が実行されます。その際に、タグが補完されるため、意図した表示にならないです。
innerHTMLプロパティへの最初のtableタグの代入直前にブレークポイントを置き、innerHTMLの値を確認します。この時は空文字列になっています。
innerHTMLプロパティに
table
タグ、
thead
タグを代入すると、タグの検証が実行され、すぐに閉じタグが自動で補完されます。innerHTMLには
<table><thead></thead></table>
の文字列が設定されます。その後に
tr
タグをinnerHTMLプロパティに代入していますが、tableタグが閉じられているため、タグは無視されます。
対処法
innerHTMLプロパティに順次文字列を設定せず、変数にすべてのHTMLタグを代入した後、
変数の文字列を一度にinnerHTMLプロパティに代入することで、正しくHTMLタグを表現できます。
プログラム例
コード
以下のHTMLファイルを作成します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
table {
border-collapse: collapse;
border: 1px solid #717171;
}
table tr th {
padding: 0.1rem 1rem 0.1rem 0.5rem;
border: 1px solid #717171;
font-size:0.8rem;
}
table tr td {
padding: 0.1rem 1rem 0.1rem 0.5rem;
border: 1px solid #717171;
}
</style>
<script type="text/javascript">
window.onload = proc;
function proc() {
var header = ["ID","品名","価格","在庫数"];
var item = [
[1, "ぺんぎんクッキー", 340, 8],
[2, "しろくまアイス", 240, 12],
[3, "かるがもサブレ", 140, 6],
[4, "ふくろうカステラ", 680, 3]
];
var elem = document.getElementById("output");
var htmlDoc;
htmlDoc = "<table><thead>"
htmlDoc += "<tr>";
for (i = 0; i < header.length; i++) {
htmlDoc += "<th>" + String(header[i]) + "</th>";
}
htmlDoc += "</tr></thead><tbody>";
for (i = 0; i < item.length; i++) {
htmlDoc += "<tr>";
for (j = 0; j < item[i].length; j++) {
htmlDoc += "<td>" + String(item[i][j]) + "</td>";
}
htmlDoc += "</tr>";
}
htmlDoc += "</tbody></table>";
elem.innerHTML = htmlDoc;
}
</script>
</head>
<body>
<h2>innerHtmlでTableタグを出力するデモ</h2>
<div id="output"></div>
</body>
</html>
解説
htmlDoc変数を宣言します。
var htmlDoc;
htmlDoc変数にタグや値の文字列を代入します。
htmlDoc = "<table><thead>"
htmlDoc += "<tr>";
for (i = 0; i < header.length; i++) {
htmlDoc += "<th>" + String(header[i]) + "</th>";
}
htmlDoc += "</tr></thead><tbody>";
for (i = 0; i < item.length; i++) {
htmlDoc += "<tr>";
for (j = 0; j < item[i].length; j++) {
htmlDoc += "<td>" + String(item[i][j]) + "</td>";
}
htmlDoc += "</tr>";
}
htmlDoc += "</tbody></table>";
htmlDoc変数の値をinnerHTMLプロパティに代入します。
elem.innerHTML = htmlDoc;
実行結果
上記のHTMLファイルをWebブラウザで表示します。下図のページが表示されます。
配列変数の値が表組されて表示されました。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用