javascript - style - vue single file components




¿Cómo puedo agregar varias imágenes junto con otros campos de entrada en vue js html? (3)

Mi código html es

También necesito agregar sez que está en formato de matriz y también debo agregar varias imágenes, debo proporcionar agregar imagen y al hacer clic en él, debo agregar imágenes según sea necesario por el cliente

<form method="POST" enctype="multipart/form-data" v-on:submit.prevent="handleSubmit($event);">
  <div class="row">
    <div class="col-md-4">
      <div class="form-group label-floating">
        <label class="control-label">Name</label>
        <input type="text" class="form-control" v-model="name">
      </div>
    </div>
    <div class="col-md-4">
      <div class="form-group label-floating">
        <label class="control-label">Alias</label>
        <input type="text" class="form-control" v-model="alias">
      </div>
    </div>
    <div class="col-md-4">
      <div class="form-group label-floating">
        <label class="control-label">Sex</label>
        <select class="form-control" v-model="sex" id="level">
        <option value="Male">Male</option>
        <option value="female">Female</option>
        </select>
      </div>
    </div>
  </div>
  <div class="row" v-for="(book, index) in sez" :key="index">


    <div class="col-md-4">
      <div class="form-group label-floating">
        <label class="control-label">Date </label>
        <input type="date" class="form-control" v-model="book.date">
      </div>
    </div>
    <div class="col-md-8">
      <div class="form-group label-floating">
        <label class="control-label"> Details</label>
        <input type="text" class="form-control" book.details>
      </div>
    </div>

  </div>
  <a @click="addNewRow">Add</a>

  <div class="card-content">
    <div class="row">
      <div class="col-md-4">
        <div class="button success expand radius">
          <span id="save_image_titlebar_logo_live">Signature</span>
          <label class="custom-file-upload"><input type="file" name="photo" accept="image/*"  />
        </label>
        </div>
      </div>
      <div class="col-md-4">
        <div class="button success expand radius">
          <span id="save_image_titlebar_logo_live">Recent Photograph</span>
          <label class="custom-file-upload">
        <input type="file" name="sign"/>
        </label>
        </div>
      </div>
    </div>
  </div>
</form>

Mi código vue js es

addForm = new Vue({
  el: "#addForm",
  data: {
    name: '',
    alias: '',
    sex: '',
    sez: [{
      date: null,
      details: null,

    }, ],
    photo: '',
    sign: '',
  },
  methods: {
    addNewRow: function() {
      this.seziure.push({
        date: null,
        details: null,
      });
    },

    handleSubmit: function(e) {
      var vm = this;
      data = {};
      data['sez'] = this.sez;
      data['name'] = this.name;
      data['alias'] = this.alias;
      data['sex'] = this.sex;
      //how to add images
      $.ajax({
        url: 'http://localhost:4000/save/',
        data: data,
        type: 'POST',
        dataType: 'json',
        success: function(e) {
          if (e.status) {
            vm.response = e;
            alert("success")

          } else {
            vm.response = e;
            console.log(vm.response);
            alert("Registration Failed")
          }
        }
      });
      return false;
    },
  },
});

Este es mi código. No tengo idea de cómo agregar imágenes en este caso.

¿Alguien puede por favor ayudarme a pasar estos datos.

¿Cómo pasar estos datos junto con las imágenes al backend?

No quiero usar la codificación base64. Necesito simplemente pasar esta imagen en esta solicitud de publicación ajax junto con otros datos


No estoy seguro de dónde desea que aparezcan las imágenes adicionales, pero las agregué después de esta columna:

<div class="col-md-4">
  <div class="button success expand radius">
    <span id="save_image_titlebar_logo_live">Recent Photograph</span>
    <label class="custom-file-upload">
  <input type="file" name="sign"/>
  </label>
  </div>
</div>

Y aquí está la columna que agregué: "agregar imágenes": (Puedes probar esta función here , con las actualizaciones)

<div class="col-md-4">
  <ul class="list-group" :if="images.length">
    <li class="list-group-item" v-for="(f, index) in images" :key="index">
      <button class="close" @click.prevent="removeImage(index, $event)">&times;</button>
      <div class="button success expand radius">
        <label class="custom-file-upload">
          <input type="file" class="images[]" accept="image/*" @change="previewImage(index, $event)">
        </label>
      </div>
      <div :class="'images[' + index + ']-preview image-preview'"></div>
    </li>
  </ul>
  <button class="btn btn-link add-image" @click.prevent="addNewImage">Add Image</button>
</div>

Y el código completo de Vue JS (con jQuery.ajax() ):

addForm = new Vue({
  el: "#addForm",
  data: {
    name: '',
    alias: '',
    sex: '',
    sez: [{
      date: null,
      details: null
    }],
    // I removed `photo` and `sign` because (I think) the're not necessary.
    // Add I added `images` so that we could easily add new images via Vue.
    images: [],
    maxImages: 5,
    // Selector for the "Add Image" button. Try using (or you should use) ID
    // instead; e.g. `button#add-image`. But it has to be a `button` element.
    addImage: 'button.add-image'
  },
  methods: {
    addNewRow: function() {
      // I changed to `this.sez.push` because `this.seziure` is `undefined`.
      this.sez.push({
        date: null,
        details: null
      });
    },

    addNewImage: function(e) {
      var n = this.maxImages || -1;
      if (n && this.images.length < n) {
        this.images.push('');
      }
      this.checkImages();
    },

    removeImage: function(index) {
      this.images.splice(index, 1);
      this.checkImages();
    },

    checkImages: function() {
      var n = this.maxImages || -1;
      if (n && this.images.length >= n) {
        $(this.addImage, this.el).prop('disabled', true);  // Disables the button.
      } else {
        $(this.addImage, this.el).prop('disabled', false); // Enables the button.
      }
    },

    previewImage: function(index, e) {
      var r = new FileReader(),
        f = e.target.files[0];

      r.addEventListener('load', function() {
        $('[class~="images[' + index + ']-preview"]', this.el).html(
          '<img src="' + r.result + '" class="thumbnail img-responsive">'
        );
      }, false);

      if (f) {
        r.readAsDataURL(f);
      }
    },

    handleSubmit: function(e) {
      var vm = this;

      var data = new FormData(e.target);
      data.append('sez', this.sez);
      data.append('name', this.name);
      data.append('alias', this.alias);
      data.append('sex', this.sex);

      // The `data` already contain the Signature and Recent Photograph images.
      // Here we add the extra images as an array.

      $('[class~="images[]"]', this.el).each(function(i) {
        if (i > vm.maxImages - 1) {
          return; // Max images reached.
        }

        data.append('images[' + i + ']', this.files[0]);
      });

      $.ajax({
        url: 'http://localhost:4000/save/',
        data: data,
        type: 'POST',
        dataType: 'json',
        success: function(e) {
          if (e.status) {
            vm.response = e;
            alert("success");
          } else {
            vm.response = e;
            console.log(vm.response);
            alert("Registration Failed");
          }
        },
        cache: false,
        contentType: false,
        processData: false
      });

      return false;
    },
  },
});

Notas adicionales

Sé que estás usando Node.js en el back-end; sin embargo, debo mencionar que en PHP, la variable $_FILES contendría todas las imágenes (siempre que el name los campos esté correctamente configurado); y supongo que Node.js tiene una variable similar o una forma de obtener los archivos.

Y en la siguiente input , puede haber olvidado envolver book.details en v-model :

<input type="text" class="form-control" book.details>
<input type="text" class="form-control" v-model="book.details"> <!-- Correct -->

ACTUALIZAR

Se agregó una función para limitar la cantidad de imágenes que se pueden seleccionar / cargar, y se agregó una vista previa para la imagen seleccionada. Además de la corrección "enviar imágenes como array ".


Si está utilizando HTML5, intente con un objeto FormData ; codificará el contenido de entrada de su archivo:

var myForm = document.getElementById('addForm');
formData = new FormData(myForm);
data: formData

Utilice debajo templete para mostrar / subir la imagen:

 <div v-if="!image">
    <h2>Select an image</h2>
    <input type="file" @change="onImageUpload">
  </div>
  <div v-else>
    <img :src="image" />
    <button @click="removeImage">Remove image</button>
  </div>

Código js:

data: {
    image: '',
    imageBuff: ''
},
methods: {
    onImageUpload(e) {
        var files = e.target.files || e.dataTransfer.files;
        if (!files.length)
            return;
        this.createImage(files[0]);
    },
    createImage(file) {
        var image = new Image();
        var reader = new FileReader();
        this.imageBuff = file;

        reader.onload = (e) => {
            this.image = e.target.result;
        };
        reader.readAsDataURL(file);
    },
    removeImage: function(e) {
        this.image = '';
    },
    handleSubmit(e) {
        const formData = new FormData();

        formData.append('name', this.name);
        formData.append('alias', this.alias);
        formData.append('sex', this.sex);
        formData.append('image', this.imageBuff);
        ...

        // Ajax or Axios can be used
        $.ajax({
            url: 'http://localhost:4000/save/',
            data: formData,
            processData: false, // prevent jQuery from automatically transforming the data into a query string.
            contentType: false,
            type: 'POST',
            success: function(data) {
                console.log(data);
                ...
            }
        });

    }
}






vue-component