in Vue js how to convert images from dynamic table to base64 format and send it json file??
Tags: javascript, vue, webdev
Published: 2022-07-18 09:52:45

Dears, I have dynamic table to add multiples rows with different image in each row, I have tried to convert images to base64 format and save the table with converted base64 images to json file, the problem that json file contains only base64 text for the first image in all table rows, I want the json files contains all base64 text for different images in the table. your help is highly appreciated

Here is my trial in vue js:

```
<template>
<v-container>
    <v-form lazy-validation ref="form">
      <v-card class="pa-5">
        <v-list-item-title class="headline mb-2 pa-1">
          information</v-list-item-title
        >

        <v-row>
          <v-text-field
            class="pa-1"
            label="Field abbreviation"
            @keyup="uppercase"
            required
            v-model="field"
            :rules="fieldRule"
            maxlength="4"
          ></v-text-field>
        </v-row>
        <v-row>
          <v-text-field
            class="pa-1"
            label="Field lines"
            @keyup="uppercase"
            required
            v-model="fieldLines"
          ></v-text-field>
        </v-row>
      </v-card>

      <table class="responsive-table">
        <thead>
          <tr>
            <th scope="col">#</th>

            <th class="text-left">Sample Depth</th>

            <th class="text-left">Sample Number</th>

            <th class="text-left">Zoom Factor</th>

            <th class="text-left">Fossil Image</th>
          </tr>
        </thead>

        <tbody>
          <tr v-for="(imageTable, index) in imageTables" :key="index">
            <td scope="row" class="trashIconContainer">
              <i
                class="far fa-trash-alt"
                @click="deleteimageRow(index, imageTable)"
              ></i>
            </td>

            <td data-label="sampleDepth">
              <input
                v-model="imageTable.sampleDepth"
                class="form-control"
                type="number"
              />
            </td>

            <td data-label="sampleNumber">
              <input
                v-model="imageTable.sampleNumber"
                class="form-control"
                type="number"
              />
            </td>

            <td data-label="ZoomFactor">
              <input
                v-model="imageTable.zoomFactor"
                class="form-control"
                type="number"
              />
            </td>

            <td>
              <v-file-input
                type="file"
                accept="image/png, image/jpeg, image/bmp"
                placeholder="Pick a Fossil photo"
                @change="uploadImage(index)"
              ></v-file-input>
            </td>

            <td>
              <button @click="deleteimageRow" class="is-danger">Delete</button>
            </td>
          </tr>
        </tbody>
      </table>

      <button type="button" class="btn btn-info" @click="addimageRow">
        <i class="fas fa-plus-circle"></i>

        Add
      </button>

      <v-row>
        <v-col>
          <v-btn
            width="100%"
            class="primary"
            :loading="isPdfGenerating"
            @click="generateReport(true)"
            >Generate draft report</v-btn
          >
        </v-col>
      </v-row>

      <v-row>
        <v-col>
          <v-btn
            width="100%"
            class="primary"
            :disabled="!isPdfGenerated"
            @click="savePdf"
            >Download generated report</v-btn
          >
        </v-col>

        <v-col>
          <v-btn
            width="100%"
            class="primary"
            :disabled="!isPdfGenerated"
            @click="generateReport(false)"
            >Make report official</v-btn
          >
        </v-col>
      </v-row>
    </v-form>
  </v-container>
</template>

<script>
export default {
  name: "Table",

  data: () => ({
    field: null,
    fieldRule:[],
    fieldLines: null,
    isPdfGenerating: false,
    isPdfGenerated: false,
    pdfData: null,
    imageUploaded: false,
    imageTables: [
      { sampleDepth: "", sampleNumber: "", zoomFactor: "", image: "" },
    ],
  }),

  created() {},

  methods: {
    addimageRow() {
      this.imageTables.push({
        sampleDepth: "",

        sampleNumber: "",

        zoomFactor: "",

        image: "",
      });  
      console.log(this.imageTables); 
    },

    uppercase(){
      //pass
    },
    deleteimageRow(index, imageTables) {
      var idx = this.imageTables.indexOf(imageTables);

      console.log(idx, index);

      this.imageTables.splice(idx, 2);
    },

    uploadImage(idx) {
      this.imageUploaded = true;
      const file = document.querySelector("input[type=file]").files[0];

      const reader = new FileReader();

      let rawImg;

      reader.onloadend = () => {
        rawImg = reader.result;
        this.imageTables[idx].image = rawImg;
      };
      reader.readAsDataURL(file);
    },

    generateReport: function (isDraft = true) {
      this.$refs.form.validate();

      this.$emit("pdfGenerated", null);

      this.isPdfGenerating = true;

      this.isPdfGenerated = false;

      let jsonData = {
        field: this.field,
        fieldlines: this.fieldLines,

        imageTables: this.imageTables,

        key: this.$store.state.key,

        isDraft: isDraft,
      };

      console.log(jsonData);

      this.$axios
        .post(this.$backendUrl + "/table", jsonData)

        .then((response) => {
          console.log(response);

          this.pdfData = { data: response.data };

          this.$emit("pdfGenerated", this.pdfData);

          this.isPdfGenerated = true;

          this.isPdfGenerating = false;
        })

        .catch((error) => {
          console.log(error);

          this.isPdfGenerating = false;

          this.isPdfGenerated = false;

          if (error.response.status == 401) {
            this.$emit("unauthorized");
          }

          if (error.response.status == 404) {
            window.alert(error.response.data.message);
          }
        })

        .then(function () {});
    },

    savePdf: function () {
      var blob = new Blob([this.pdfData.data], { type: "application/pdf" });

      var link = document.createElement("a");

      link.href = window.URL.createObjectURL(blob);

      var fileName = "Output";

      link.download = fileName;

      link.click();
    },
  }
};
</script>

<style scoped>
@media (min-width: 761px) {
  .header {
    display: flex;
  }
}

@media (min-width: 761px) {
  .header > div:nth-child(-n + 1) {
    order: 1;

    flex: 1;

    text-align: right;

    padding-left: 1rem;
  }
}

.section-spacer {
  margin: 1rem 0;
}

input,
select,
textarea {
  background-color: rgb(245, 243, 237);

  /* background-color:#ffc371; */

  border: none;

  border-top: 2px solid #ffc371;

  border-bottom: 2px solid #ffc371;

  border-left: 2px solid #ffc371;

  border-right: 2px solid #ffc371;

  border-radius: 5px;

  display: inline-block;

  transition: background-color 0.3s ease-in-out;

  width: 100%;
}

input:focus,
select:focus,
textarea:focus {
  outline-color: #ffc371;

  background-color: rgba(255, 255, 255, 0.6);
}

input:hover,
select:hover,
textarea:hover {
  background-color: rgba(255, 255, 255, 0.5);
}

@media print {
  input,
  select,
  textarea {
    background-color: transparent;
  }
}

textarea {
  width: 100%;

  min-height: 80px;
}

table {
  width: auto;

  border-collapse: collapse;

  margin: 4rem 0;
}

table thead th {
  padding: 0.5rem 1rem;
}

table thead th:nth-child(-n + 1) {
  padding-left: 0;
}

table thead th:nth-last-child(-n + 1) {
  padding-right: 0;
}

table tr {
  border-bottom: 1px solid #f4d4aa;
}

table tr td {
  padding: 0.5rem 1rem;
}

table tr td:nth-child(-n + 10) {
  padding-left: 0;
}

table tr td:nth-last-child(-n + 1) {
  padding-right: 0;
}

table tr td input {
  width: 100%;
}

table tr td .cell-with-input input {
  margin: 0 0.2rem;
}

.responsive-table {
  width: 100%;
}

@media only screen and (max-width: 760px) {
  .responsive-table table,
  .responsive-table thead,
  .responsive-table tbody,
  .responsive-table th,
  .responsive-table td,
  .responsive-table tr {
    display: block;
  }

  .responsive-table thead tr {
    position: absolute;

    top: -9999px;

    left: -9999px;
  }

  .responsive-table tr {
    padding: 2rem 0;
  }

  .responsive-table td[data-label] {
    position: relative;

    padding-left: 100;

    display: flex;

    align-items: right;
  }

  .responsive-table td[data-label]:before {
    content: attr(data-label);

    position: absolute;

    top: 0.5rem;

    left: 0;

    width: 35%;

    padding-right: 10px;

    white-space: nowrap;

    font-weight: bold;
  }
}

button {
  background-color: #81cf71;

  border: none;

  border-radius: 100px;

  padding: 0.5rem 1rem;

  cursor: pointer;

  transition: background-color 0.3s ease-in-out;
}

button:focus {
  outline-color: #ffc371;

  background-color: #69c656;
}

button:hover {
  background-color: #70c95e;
}

@media print {
  button {
    display: none;
  }
}

button.is-danger {
  background-color: #ff5f6d;
}

button.is-danger:focus {
  background-color: #ff3b4c;
}

button.is-danger:hover {
  background-color: #ff4656;
}

.text-right {
  text-align: right;
}

.text-bold {
  font-weight: bold;
}
</style>
```