JavaScriptの関数の実行タイミングを一番最後にしたい
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 629
やりたいこと
Ruby on Railsを使ってWebアプリケーションを作成しています。
nested_form_fieldsというgemを使って、動的に画像アップロードフォームを含めた入力フォームを動的に追加できる機能を実装しており、この追加された画像アップロードフォームのそれぞれに対して画像プレビュー機能をつけたいと考えています。
// _form.html.slim
= f.nested_fields_for :gears, wrapper_tag: :div do |g|
.item
.row
.col-6
.form-group
= g.label :gear_image
- if g.object.gear_image?
= image_tag(g.object.gear_image.url, id: 'preview__nested_field_for_replace_with_index__', class: 'gear_image')
- else
= image_tag('nofile.jpg', id: 'preview__nested_field_for_replace_with_index__', class: 'gear_image')
= g.file_field :gear_image, class: "form-control-file gear-file-form"
.col-6
.form-group
= g.label :name
= g.text_field :name, class: "form-control"
.form-group
= g.label :brand
= g.text_field :brand, class: "form-control"
.form-group
= g.label :kind
= g.select :kind, gear_type_list, { include_blank: true }, class: "form-control"
.form-group
= g.label :model_year
= g.text_field :model_year, class: "form-control"
= g.remove_nested_fields_link '削除', class: 'btn btn-danger', role: 'button'
= f.add_nested_fields_link :gears, '+', class: 'btn btn-primary', role: 'button', id: 'add-form'
// application.js
document.addEventListener('DOMContentLoaded', function () {
var index = 1;
var fuga = '#preview';
document.getElementById('add-form').addEventListener("click", function () {
index += 1;
// とりあえず以下2通り試しましたがフォーム作成前に実行されてしまいます。
hogehoge(index); // 1
window.onload = hogehoge(index); // 2
}, false);
// 関数①
function hogehoge(index) {
for (var i = 0; i < index; i++) {
(function (j) {
fuga += j.toFixed();
var id = 'article_gears_attributes_' + j + '_gear_image';
document.getElementById(id).addEventListener("change", function (evt) {
var file = evt.target.files;
var reader = new FileReader();
reader.readAsDataURL(file[0]);
reader.onload = function () {
document.querySelector(fuga).src = reader.result;
}
}, false);
}(i));
}
};
window.onload = hogehoge(index);
});
問題点
JavaScriptで
- フォームの数だけ画像アップロードフォームにイベントを追加する関数hogehogeを定義・・・①
- ページ読み込み時に①を実行
- フォームの追加ボタン(画像では+ボタン)を押下した時に①の関数hogehogeを再実行
という流れを思い浮かべていたのですが、3.でフォームがnested_form_fieldsによって追加される前に
①の関数hogehogeが実行されてしまい、Uncaught TypeError: Cannot read property 'addEventListener' of null
を吐いてしまいます。
フォームが追加された後に関数hogehogeを実行させるようにしたいのですが、なにか良いやり方はないでしょうか?
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
こんにちは、m-88888888さん
質問拝見しました。
早速ですが、問題点の3は、おそらくwindow.onload
に、hogehoge
メソッドを実行した返り値を渡すようになっているからだと思います。
window.loadに渡せるのは、関数自体になるので、質問と同じ条件でindexを渡した状態で関数を渡したいのであれば、bind
メソッドを利用すると良いと思います。
こうすれば、 DOMContentLoaded
イベント時に、window.onload
がセットアップされ、load
イベントが完了したあとに、indexを捕捉した状態でhogehogeメソッドが実行されます。
window.load
Function.prototype.bind()
// application.js
document.addEventListener('DOMContentLoaded', function () {
...(省略)
window.onload = hogehoge.bind(this, index);
});
以上、参考になれば、幸いです。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.33%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2019/12/31 17:39
おそらく今回の問題とはまた別?だと思うので、こちらは自分で取り組んでみます。
この度はご回答いただき誠にありがとうございました!