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

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

ただいまの
回答率

88.92%

htmlをビューにappendする際に要素の中に@changeもしくはv-on:を追加したい。

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 170

tenlife

score 42

laravelで画像の複数枚投稿を実装しています。

解決したいこと: 新しく作るhtml要素に@changeもしくはv-onをつける。

現状: html要素として表示されてしまう。発火しない。

現在は写真を追加した際に新しいinput要素を作るようにしています。
そのイベントの発火でvue.jsの@changeを使用しています。
しかし、新しく追加するinput要素に@change をうまく付与することが出来ません。
削除の部分も同様です。

<div class="form-group" id="image">
  <label for="photo">写真</label>
  <input type="file" name="src" @change='onFile'>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  new Vue({
            el: '#image',
            data: {
                photos: [],
                fileIndex: [1,2,3]
            },
            methods: {
              buildinput(index) {
                  let html = `<div data-index="${index}" class="js-file_group">
                                <input type="file" name="src[${index}]" @change='onFile'>
                                <div class="js-remove" @change='delete_image'>削除</div>
                              </div>`
                  return html;
                },

              onFile(e) {
                this.photos = e.target.files
                $('#image').append(this.buildinput(this.fileIndex[0]))
              },
              delete_image(){
                console.log('テスト')
              }            
            }
          })
</script>

書き方の問題な気がするのですが、正しい記述方法が見つけられませんでした。

どなたか知恵を貸していただけないでしょうか?
よろしくお願いします。

laravel6.18
vue 2.6.11

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • zushi0905

    2020/07/07 11:11

    $('#image').append(this.buildinput(this.fileIndex[0]))
    ↑この書き方ってjQueryじゃないですかね?

    キャンセル

  • tenlife

    2020/07/07 15:04 編集

    ご指摘ありがとうございます。
    templateで用意して、v-htmlで出すという流れで認識あっていますでしょか?
    https://qiita.com/Yorinton/items/a0144c34e4edb0777493#15props%E3%81%AB%E6%B8%A1%E3%81%95%E3%82%8C%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92templatemethodsupdated%E7%AD%89%E3%81%A7%E4%BD%BF%E3%81%86

    引数等は上記のサイトのようなイメージでしょうか?
    引数等の渡し方で参考になるようなサイトをご存知であれば教えていただけますでしょうか?

    キャンセル

  • zushi0905

    2020/07/07 17:53

    templateを用意してというか、html部分がもうtemplateなんで。。。
    v-htmlというか双方向データバインディングでphotosをvueオブジェクトの中に持たせて、あとはレンダリングはライフサイクルに委ねてレンダリング走らせればいいだけです。
    簡単にいうと、jQueryで実装する形だとデータを取得して整形して出力するのに対して、Vueは出力はもともと決めてあって、データを格納する変数に入れてあげるだけって感じです。

    引数はjqueryと同じでイベントとして使っているメソッドは引数にイベントオブジェクトを渡され、普通のメソッドとして定義しているものはphpと同じような関数です。

    キャンセル

  • tenlife

    2020/07/08 11:34

    返信ありがとうございます。
    提示していただいたやり方と全く同じではないかもしれませんが、双方向データバインディング考え方参考にさせていただきました。

    <div class="form-group">
    <div>
    <h2>Select an image</h2>
    <input type="file" @change="onFileChange">
    </div>
    <div v-if="images">
    <ol>
    @{{images}}
    <li v-for="(image, index) in images">
    <h5>@{{image.name}}</h5>
    <img :src="image.thumbnail" style="width: 100px; height: 100px;" />
    <input type="hidden" v-model="image.name">
    <div @click="edit(index)">Edit image</div>
    <div @click="remove(index)">Remove image</div>
    </li>
    </ol>
    </div>
    </div>


    data() {
    return {
    images: []
    }
    },
    methods: {
    onFileChange(e) {
    let files = e.target.files
    this.createImage(files[0])
    },
    createImage(file) {
    let obj = {};

    const reader = new FileReader();

    reader.onload = (e) => {
    obj.thumbnail = e.target.result;
    obj.name = file.name

    this.images.push(obj)
    };
          reader.readAsDataURL(file);
    },

    キャンセル

回答 2

+1

vueとjQueryは共存させることは可能ですがこの書き方だとダメですね。
photos をv-forでループさせる形にしてjQueryを外すべきです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/08 11:38

    提示された方向で作成し直したところ、photosに格納することができました。
    ありがとうございました!

    キャンセル

check解決した方法

-1

下記のような流れでimagesに格納することができました。

photosからimagesに変更されています。

<div class="form-group">
      <div>
        <h2>Select an image</h2>
        <input type="file" @change="onFileChange">
      </div>
      <div v-if="images">
          <ol>
              <li v-for="(image, index) in images">
                <h5>@{{image.name}}</h5>
                <img :src="image.thumbnail" style="width: 100px; height: 100px;" />
                <input type="hidden" v-model="image.name">
                <div @click="edit(index)">Edit image</div>
                <div @click="remove(index)">Remove image</div>
              </li>
          </ol>
      </div>
    </div>
       data() {
              return {
                images: []
              }
            },
            methods: {
              onFileChange(e) {
                let files = e.target.files
                this.createImage(files[0])
              },
              createImage(file) {
                let obj = {};
                const reader = new FileReader();
                reader.onload = (e) => {
                    obj.thumbnail = e.target.result;
                    obj.name = file.name
                    this.images.push(obj)
                };
                reader.readAsDataURL(file);
              },

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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