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

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

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

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

Smarty

Smartyは、PHPアプリケーションで使用されるテンプレートエンジンです。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

2回答

5347閲覧

htmlとjavascript間の配列データ受渡について

kumakumatan

総合スコア213

JavaScript

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

Smarty

Smartyは、PHPアプリケーションで使用されるテンプレートエンジンです。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

1クリップ

投稿2018/01/15 06:31

編集2018/01/16 01:49

データ構造($test_list)

array(2) { [0]=> array(3) { ["test_name"]=> string(15) "テスト太郎" ["test_d_name"]=> string(6) "太郎" ["test_address"]=> string(6) "東京" } [1]=> array(3) { ["test_name"]=> string(15) "テスト花子" ["test_d_name"]=> string(6) "花子" ["test_address"]=> string(6) "大阪" } }

■実現したい事
(1)「名前を追加」ボタンにて、ラベルを追加して、同じように「選択してください」ラベルから選んだ「$test_list[idx].test_name」から
同じ配列インデックスの「test_d_name」と「test_address」の値をテキストボックスに表示させたいです。

idの重複はjavascriptではNGなので「test.tpl」の「id="select_test_info"」を「id="select_test_info1"」として、
「名前を追加」ボタンを押して、ラベル追加した際2番目のidが「id="select_test_info2"」3番目のidが「id="select_test_info3"」
となっていくのでtplの下記部分をそれに対応したように、「document.getElementById('select_test_info2').addEventListener」
「document.getElementById('select_test_info3').addEventListener」となるようにしたいのですが、どのように
したら良いかわからなく悩んでいます。

(2)ラベルを「選択してください」に戻すと、テキストボックス欄が「undefined」となってしまいます。
tplの下記部分に、

if ( option.indexOf("選択してください") != -1) { document.querySelector('input[name^="test_d_name"]').value = option.dataset.disp; }

と記載して、「選択してください」ラベルがない場合のみ表示させようとしているのですが、うまく
いかなく悩んでいます。

以上の2点をどのようにしたら良いかご教授いただきたくお願い致します。
●test.tpl

html

1<script language="JavaScript" src="test.js?t={$smarty.now}"></script> 2 3456 7<h3 class="Test_header">テスト</h3> 8<table data-role="table" id="test_tab" data-mode="reflow" class="ui-responsive table-stroke"> 9<thead> 10 <tr> 11 <th width="5%">メイン</th> 12 <th width="30%">名前</th> 13 <th width="30%"></th> 14 <th width="30%">住所</th> 15 <th width="5%">削除</th> 16 </tr> 17</thead> 18<tbody id="test_tbody"> 19{assign var='i' value=0} 20 21<tr> 22 <td><input type="radio" id="in_test_radio{$i}" name="test_radio[{$i}]"/></td> 23 <td> 24 <select name="test_info" id="select_test_info1" data-native-menu="true"> 25 <option value="">選択してください</option> 26 {section name=idx loop=$test_list} 27 <option value="{$test_list[idx].test_name|escape:"html"}"{if $test_list[idx].test_name == $test_list} selected{/if} data-disp="{$test_list[idx].test_d_name}" data-address="{$test_list[idx].test_address}">{$test_list[idx].test_name}</option> 28 {/section} 29 </select> 30 </td> 31 <td><input type="text" name="test_d_name[{$i}]" value="{$test_list[idx1].test_d_name|escape:"html"}" placeholder="" /></td> 32 <td><input type="text" name="test_address[{$i}]" value="{$test_list[idx1].test_address|escape:"html"}" placeholder="住所" /></td> 33 <td><button type="button" id="btn_del_test{$i}" class="deleteTest ui-btn ui-shadow ui-corner-all ui-btn-icon-left ui-icon-delete">削除</button> 34</tr> 35</tbody> 36</table> 37 38<div class="ui-field-contain"> 39 <button type="button" id="btn_addName" class="addName ui-btn ui-shadow ui-corner-all ui-btn-icon-left ui-icon-plus">名前を追加</button> 40</div> 41424344</div> 45 <script type="text/javascript"> 46 var next_idx = $('#test_tbody').children().length; 47// console.log(next_idx); 48 document.getElementById('select_test_info').addEventListener('change', function(event) { 49 var option = this.options[this.selectedIndex]; 50// console.log(option); 51// if ( option.indexOf("選択してください") != -1) { 52 document.querySelector('input[name^="test_d_name"]').value = option.dataset.disp; 53// } 54 document.querySelector('input[name^="test_address"]').value = option.dataset.address; 55 }, false); 56 </script> 57</body> 58</html>

●test.js(「名前を追加」ボタンを押した際)

js

1//名前の行を追加する 2$(document).on("click", ".addName", function() 3{ 4 var content = ''; 5 var next_idx = $('#test_tbody').children().length; 6 next_idx++; 7 content += '<tr>'; 8 content += '<td><input type="radio" id="in_test_radio{$i}" name="test_radio['+next_idx+']" value="'+next_idx+'" /></td>'; 9 content += '<td><select name="test_info" id="select_test_info'+next_idx+'" data-native-menu="true">'; 10 content += '</select></td>'; 11 12 content += '<td><input type="text" name="test_d_name['+next_idx+']" value="" placeholder="名" /></td>'; 13 content += '<td><input type="text" name="test_address['+next_idx+']" value="" placeholder="住所" /></td>'; 14 content += '<td><button type="button" id="btn_del_test'+next_idx+'" class="deleteTest ui-btn ui-shadow ui-corner-all ui-btn-icon-left ui-icon-delete">削除</button></td>'; 15 content += '</tr>'; 16 $('#test_tbody').append(content); 17 // selectの中身を足す 18 $('#select_test_info'+next_idx).append($('#select_test_info').children().clone(true)); 19 //Table Tag 再構築 20 $('#test_tbody').trigger('create'); 21 22 return false; 23});

となっております。
ご教授いただきたくお願い申し上げます。
宜しくお願いします。

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

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

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

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

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

guest

回答2

0

そもそもPHPとSmartyとJavaScriptとブラウザの関係がちゃんと理解出来てなさそうなので、
ざっと解説します。
まずは下記のような流れになります。

  1. ブラウザにURLを打ち込んだりリンクで訪問
  2. ブラウザ「Webサーバさん、HTMLください」
  3. Webサーバ「お、このURLはPHPで解析しないと駄目だな…ちょっとまってて、おいPHPさんお客さんだよ!」
  4. PHP「おっ、HTMLの要望かよしよし加工したろ。これはSmartyで変換しないとだめだな、ちょっと値やるからHTMLちょうだい」
  5. Smarty「承知、HTMLできました」
  6. PHP「Smartyさんありがと、WebサーバさんHTMLだよ」
  7. Webサーバ「PHPさんありがと、ブラウザさんおまたせしましたHTMLです」
  8. ブラウザ「ありがと、<script language="JavaScript" src="test.js?t={$smarty.now}"></script>っていう記述あるからもう一回お願いしなきゃ駄目だな」
  9. ブラウザ「Webサーバさん、test.jsください」
  10. Webサーバ「承知しました。Linuxマシンのディレクトリにtest.jsがありましたのでお返しします。」
  11. ブラウザ「Webサーバさんありがとう、よし解析するか…」
  12. ブラウザ「ん?この{}で書かれた変な書式はなんだ?まぁ文字列だからいいか」

この時重要なのは、隣同士の概念しかお互いに知らない事。
ブラウザはHTMLやJavaScriptファイルを受け取って解釈することであり、
裏でPHPだろうがNode.jsだろうが何で動いていようがHTMLを受け取ればそれに従って動作するだけと割り切っていることです。

関係を表すとこうです。
お互いは隣同士の存在しか認知していません。
ブラウザ -> Webサーバ -> PHP -> Smarty

sousukeさんの仰っているのはまさにそこで、
ブラウザもWebサーバもSmartyの事なんて知ったことではないので、
test.jsにSmarty流の書式を持ち込む事は出来ません。


どのようにしたらできますでしょうか?

まず、Smarty変数はHTMLが完成してPHPに戻ってきた瞬間に全てなくなっていますので、
ブラウザが再利用する手段はありません。
これに関しては、予めHTML側にテンプレート的な存在のDOMを作っておく解決方法があります。

HTML

1<div id="templates" style="display: none;"> 2 <div class="select"> 3 <select name="test_info" id="select_test_info" data-native-menu="true"> 4 <option value="">選択してください</option> 5 {section name=idx loop=$test_list} 6 <option value="{$test_list[idx].test_name|escape:"html"}"{if $test_list[idx].test_name == $test_list} selected{/if} data-disp="{$test_list[idx].test_d_name}" data-address="{$test_list[idx].test_address}">{$test_list[idx].test_name}</option> 7 {/section} 8 </select> 9 </div> 10</div>

まぁ、idは同じHTML内で重複してはならないのでid="select_test_info"は一発アウトです。
同様に id="btn_del_test{$i}"というふうな記述が散見されますが、
select name="test_info"とあるようにどうしても重複を避けるべき理由はなさそうですね。

どうしてもSmarty変数を再利用したい

Smartyを抜けた瞬間にSmarty変数は全てなくなりますが、
JavaScriptの変数はブラウザがHTMLを読み始めて初めて単なる文字列からJavaScriptのコードになります。
つまり、SmartyでJavaScriptの構文を出力して残しておけば、ブラウザにSmarty変数の中身を渡す事が可能です。

しかしJavaScriptの構文である{}とSmartyの{}がもろに衝突するので、このままでは使えません。
一般的にはSmartyの展開用の構文を{{}}等に変更して対処することが多いです。

HTML

1<script> 2var test_list = []; 3{{section name=idx loop=$test_list}} 4 test_list.push({ 5 id: {{idx}}, 6 name: {{$test_list[idx].test_name}}, 7 value: {{$test_list[idx].test_name|escape:"html"}}, 8 is_selected: {{if $test_list[idx].test_name == $test_list}}true{{else}}false{{/if}}, 9 display_name: {{$test_list[idx].test_d_name}}, 10 address: {{$test_list[idx].test_address}} 11 }); 12{{/section}} 13 14console.log(test_list); 15</script>

このような形式で用意しておけば、JavaScriptでfor文なりなんなりを使ってDOMツリーを生成する手段が使えます。

投稿2018/01/15 09:07

miyabi-sun

総合スコア21158

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

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

kumakumatan

2018/01/16 01:50

ありがとうございます。 質問の説明文を変更して疑問点をまとめましたので、引き続き宜しくお願いします。
guest

0

Smartyはよく存じ上げないのですがクライアント側のjavascriptで
サーバーサイド(tpl)のコードを書いても解釈してもらえないと思います。

#追記
実験はしていませんが…

html

1<select name="test_info" id="select_test_info" data-native-menu="true">

ここの中身をコピーするといいのではと見ました。もともとですがid="select_test_info"などが重複してます…

長いので削除しました。

こんな感じでしょうか…他にも色々サーバー側の記述がありますが都度変更してください。

#再追記
毎回イベントリスナーをaddするのは面倒なのでselectと値を代入するtextは何かしらの
関連性を使って代入するといいと思います。

javascript

1$(document).on('change','select',function(){ 2 //changeしたselectが入っているtdから見て1つ右のtdのinputに代入 3 $($(this).parents("td").eq(0)).nextAll().eq(0).children("input").eq(0).val("aaa"); 4 //changeしたselectが入っているtdから見て2つ右のtdのinputに代入 5 $($(this).parents("td").eq(0)).nextAll().eq(1).children("input").eq(0).val("bbb"); 6});

投稿2018/01/15 06:46

編集2018/01/16 04:45
sousuke

総合スコア3828

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

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

kumakumatan

2018/01/15 07:28

ありがとうございます。 どのようにしたらできますでしょうか? 宜しくお願いします。
kumakumatan

2018/01/16 01:50

ありがとうございます。 質問の説明文を変更して疑問点をまとめましたので、引き続き宜しくお願いします。
kumakumatan

2018/01/16 04:56

ご回答ありがとうございます。 $(document).on('change','select_test_info',function(){ //changeしたselectが入っているtdから見て1つ右のtdのinputに代入 $($(this).parents("td").eq(0)).nextAll().eq(0).children("input").eq(0).val("test_d_name"); //changeしたselectが入っているtdから見て2つ右のtdのinputに代入 $($(this).parents("td").eq(0)).nextAll().eq(1).children("input").eq(0).val("test_address"); }); とするのでしょうか? また {section name=idx loop=$test_list} <option value="{$test_list[idx].test_name|escape:"html"}"{if $test_list[idx].test_name == $test_list} selected{/if} data-disp="{$test_list[idx].test_d_name}" data-address="{$test_list[idx].test_address}">{$test_list[idx].test_name}</option> {/section} はどのように変更するのでしょうか? data-disp="{$test_list[idx].test_d_name}" data-address="{$test_list[idx].test_address}" がいらなくなるのでしょうか? 宜しくお願いします。
sousuke

2018/01/16 05:15

.val("test_d_name")はやってみたのでしょうか?言われたとおりに書いてもダメですよ。 最初の質問とかなり違っているのでやりたいことを整理した方がいいと思います。 {section name=idx loop=$test_list}~~{/section} ↑ここはなんども言われているようにサーバー側のスクリプトでjavascriptとは一切関係ありません。
kumakumatan

2018/01/16 06:02

ご回答ありがとうございます。 試してみたのですが、値がセットされませんでしたので、どのようにしたら値が反映 されるかを知りたくお聞きしました。 <select name="test_info" id="select_test_info" data-native-menu="true"> ・ ・ ・ </select> ・ ・ ・ <div class="ui-field-contain"> <button type="button" id="btn_addTest" class="addTest ui-btn ui-shadow ui-corner-all ui-btn-icon-left ui-icon-plus">名前を追加</button> </div> <script type="text/javascript"> document.getElementById('select_test_info').addEventListener('change', function(event) { var option = this.options[this.selectedIndex]; document.querySelector('input[name^="test_d_name"]').value = option.dataset.name; document.querySelector('input[name^="test_address"]').value = option.dataset.address; }, false); </script> この状態では、「名前を追加」ボタンにて「test.js」側にて // selectの中身を足す $('#select_test_info'+next_idx).append($('#select_test_info').children().clone(true)); と「select_test_info」の値が「select_test_info2」となり (1)document.getElementById('select_test_info').addEventListener('change', function(event) { の処理が通らなくなり、こまっています。 また、 (2)ラベルを「選択してください」に戻すと、テキストボックス欄が「undefined」となってしまいます。 tplの下記部分に、 if ( option.indexOf("選択してください") != -1) { document.querySelector('input[name^="test_d_name"]').value = option.dataset.disp; } として、「選択してください」ラベルがない場合のみ表示させようとしているのですが、うまく いかなく悩んでいます。 どうぞ宜しくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問