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

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

ただいまの
回答率

90.46%

  • JavaScript

    21076questions

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

JSで属性を変更した後のinputのデータを削除したい

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 160

hiro610

score 2

前提

画像をアップロードするとプレビュー画像が表示されます。
そしてプレビュー画像と連動して、inputに画像データが入る仕組みになっています。
4つプレビュー画像が表示される仕組みで、それぞれidが0-3まで振られております。
![イメージ説明](3db2960246c8c7776c1cc90994388943.png)

イメージ説明

例えば2番目の画像(idがupload-form-1)を削除すると、upload-form-2はupload-form-1に変化する仕組みになっています。

実現したい事

プレビュー画像を消した際に、inputに入っている画像データを削除したいです。
1つ目の削除は成功しますが、2つ目以降の削除はできない状況です。
upload-form-1を削除した後、upload-form-2がupload-form-1に変化し、そのupload-form-1を削除しようとするとできない状況です。

エラー文
product_image_upload.self-dba68cdfccdaaa5a7b0f47bb03e77ba367404159be91200b746990224297fc9b.js?body=1:131 
Uncaught TypeError: Cannot read property 'remove' of null
    at HTMLAnchorElement.<anonymous> (product_image_upload.self-dba68cdfccdaaa5a7b0f47bb03e77ba367404159be91200b746990224297fc9b.js?body=1:131)
    at HTMLDocument.dispatch (jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5227)
    at HTMLDocument.elemData.handle (jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:4879)

原因

ドラッグアンドドロップした際に、画像データをinputに引き渡す仕組みで実装しております。

// 指定部分に画像をドロップした際の処理
  droparea.addEventListener('drop', function (e) {
    e.stopPropagation();
    // ドロップ時にファイルが開かないようにする
    e.preventDefault();
    // アップロードされた画像ファイルデータの取得
    var uploaded_file_data = e.dataTransfer.files;

    // 1番目にドロップさたものは1番目のinputタグに、2番目は2番目のinputタグにといったようにのD&Dされた画像データをinputタグに入れ込むために、プレビュー画像のliタグのidと連動させる。
    var preview_count = PreviewCount();

    // D&Dのデータを指定のinputタグに入れ込む(生成されているinputタグの個数をidに組み込むことで、ドロップとinputへの入れ込みを連動させる)
    document.getElementById('upload-form-' + preview_count).files = uploaded_file_data

    // プレビューを表示するための画像データを取得
    const reader = new FileReader();
    reader.readAsDataURL(e.dataTransfer.files[0]);
    reader.onload = function (e) {
      var upload_image = e.target.result
      // プレビュー表示の関数を呼び出す
      appendImage(upload_image);
      ImageCount();
      PreviewCount();
    }
  });

  // inputタグにデータが入る毎に新しいinputフォームを作成する
    $("#drop").change(function(e) {
      var upload_form = $("#drop")

      // プレビュー画像と連動し、idが変わったinputタグを生成するため、初期値0のPreviewCountに+1したものを変数に定義しidに組み込む
      var preview_count = PreviewCount() + 1;

      // inputタグが4つになったら追加を止める、すなわちi_countが4以上になったら追加を止める条件式。
      if (preview_count <= 4){
        var input_form = `<input class='product_images' id='upload-form-${preview_count}' multiple='multiple' name='images[image][]' type='file'>`
        // inputタグに画像データが投入されたら、新たなinputタグを生成する
        upload_form.append(input_form);
      }
    });


  // D&Dされた画像のプレビューを表示
  function appendImage(upload_image){
    // var i_count = ImageCount() + 1;
    var upload_area = $(".sell-dropbox-items ul");
    var html = `<li class='sell-dropbox-items_container'>
                    <div class='sell-dropbox-items-figure'>
                        <img alt='商品画像' src='${upload_image}'>
                    </div>
                    <a class="sell-dropbox-items-btn sell-image_edit">
                      <p>編集</p>
                    </a>
                    <a class="sell-dropbox-items-btn sell-image_delete">
                      <p>削除</p>
                    </a>
                </li>`
    upload_area.append(html);
  }

そして削除機能は以下のように実装しております。

  // 削除機能
  $(document).on("click",".sell-image_delete",function(e) {
    $(this).parent().remove();
    var delete_obj = this.parentNode;
    var delete_obj_id = delete_obj.id;
    var delete_input_data = document.getElementById('upload-form-' + delete_obj_id);
    delete_input_data.remove();
    ImageCount();
    PreviewCount();
    InputCount();

  });

コード

おそらく原因は以下でないかと考えております。
// アップロードされた画像ファイルデータの取得
var uploaded_file_data = e.dataTransfer.files;
によってinputにデータを受け渡している。→削除するとinputのidが変わる。→しかしアップロードした際に引き渡したinputのidは削除前のものに引き渡されている。
jsでidの変更は行われているが、画像データの引き渡しとは連動していない。
具体的には、
ドラッグアンドドロップをする→inputのidがupload-form-2のものに画像ファイルが引き渡される。
upload-form-1のプレビューを削除→input(idがupload-form-1)のデータが削除され、upload-form-2がupload-form-1に変化する。
そのupload-form-1を削除する、しかし画像データはupload-form-2のものに引き渡したため、画像データがない(以下のエラー文が発生する)=削除イベントが実行されない。(javascriptは一度htmlを読み込んだ後に実行されるため、見た目でidは変化しているが、htmlは再度読み込まれていないため)

Uncaught TypeError: Cannot read property 'remove' of null

対策として考えた事

削除イベント実施後、ページを再度リロードしてDOMの読み込みを実施すればいけるかも?と思いましたが、それを行うとアップロードした画像が全てリセットされてしまいました。(当たり前でした・・・)

教えていただきたい事

イメージはメルカリの商品出品時の画像アップロード機能です。
アップロードされた画像を消した際に、新たなidが付与され、その新たなidが付与されたものも削除したい場合どのように実装すれば良いでしょうか?

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • asahina1979

    2019/01/05 13:57

    ? 
    <input type=image multiple> 自体で複数アップできるのになんで複数<input type=image multiple>  をかいてるの?
    個数上限でエラーにすればいいだけだよね

    同タグを複数使う理由は?
    サーバー上で 3次元配列になるきがするけどな・・・・・

    キャンセル

  • hiro610

    2019/01/05 14:05

    multipleは過去の実装のままの状態で進めてしましました。multipleなしでの実装を検討しております。
    その場合上記の行いたい事は可能でしょうか?
    そもそもjavascriptでは難しいのでしょうか・・・?

    キャンセル

回答 2

0

まあいいや、IDを振る必要はありません。
※ 現実装のイメージでファイルがアップロードできないとかは確認してません。

処理イメージ

ドラッグ追加時

  1. 画像反映処理
  2. $(".product_images:last") セレクタを利用して削除

ファイル選択時

  1. 画像反映処理
  2. $(".product_images").val(""); 等で入力値をクリア
  3. $(".product_images:last") セレクタを利用して削除

ファイル削除

  1. タグの削除処理
  2. <input type=file class="product_images">  の復帰処理

こんな感じになると思います。
※ アップロードの可否は保証しません

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/05 14:38

    ご回答ありがとうございます、
    試してみます。

    キャンセル

0

全体は見ていませんが、エラー箇所はここ。

//    var delete_input_data = document.getElementById('upload-form-' + delete_obj_id);
//    delete_input_data.remove();
//    ↓
      $('upload-form-' + delete_obj_id).remove();

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.46%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • JavaScript

    21076questions

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