2

i have a vue app form that has an image uploader by ant-design-vue upload. i linked this image uploader to a new components that process the image to crop after upload by using cropper.js. for the first time crop everything were fine and worked perfectly. but when the user need to change the photo and crop again for the second time, the image on the crop area still using the first image. the third upload will crop the second area and next will received the same impact.

this is the structure of my code :

<template>
  <div>
    <a-row :gutter="16">
      <img ref="image" :src="initialImage">
    </a-row><br />
    <a-row :gutter="16">
      <a-button type="primary" style="float: right;" @click="crop">Crop</a-button>
      <a-button style="float: right; margin-right: 5px;" @click="cancel">Cancel</a-button>
    </a-row>
  </div>
</template>

and this is the script and style:

<script>
import Cropper from 'cropperjs';

export default {
  name: 'PostCropper',
  props: {
    uploadedImage: String,
  },
  data() {
    return {
      cropper: {},
      updatedImage: {},
      initialImage: this.uploadedImage,
    };
  },
  methods: {
    crop() {
      this.$emit('update-image', this.updatedImage);
    },
    cancel() {
      this.$emit('cancel-upload');
    },
    cropImage() {
      this.cropper = new Cropper(this.$refs.image, {
        autoCropArea: 1,
        cropBoxResizable: false,
        zoomOnTouch: true,
        zoomable: true,
        scalable: false,
        aspectRatio: 1,
        resizable: false,
        crop: () => {
          const canvas = this.cropper.getCroppedCanvas();
          this.updatedImage = canvas.toDataURL('image/png');
        },
      });
    },
  },
  watch: {
    uploadedImage() {
      this.cropper.destroy();
      this.initialImage = this.uploadedImage;
      this.cropImage();
    },
  },
  mounted() {
    this.cropImage();
  },
};
</script>

<style lang="scss">

.cropper-crop-box .cropper-view-box {
    border-radius:50%;
  }
</style>

the problem occur in here:

          this.cropper = new Cropper(this.$refs.image, {
            autoCropArea: 1,
            cropBoxResizable: false,
            zoomOnTouch: true,
            zoomable: true,
            scalable: false,
            aspectRatio: 1,
            resizable: false,
            crop: () => {
              const canvas = this.cropper.getCroppedCanvas();
              this.updatedImage = canvas.toDataURL('image/png');
            },
          });

where i have destroy the this.cropper but still crop the same image. i have tried to preview by console.log the every value for this.cropper, this.image, this.initialImage, this.uploadedImage but all of them worked with no problem. it will carry new value on this.uploadedImage is change by using vue watch. i don't know why only this function above still carry the same image. is there any way i could initialize back the this.cropper or maybe a way that can overcome my problem like rerender this child components?

Khairul Habib
  • 452
  • 1
  • 12
  • 29
  • i have overcome this problem but destroy the child component with v-if. is it proper or there is another proper way? but it's worked perfectly – Khairul Habib Dec 18 '19 at 03:09

2 Answers2

0

You can refresh Vue elements by giving them a key and updating the key. For example, where you are importing your PostCropper component:

<PostCropper v-bind:key="refreshValue" />

And then in the parent element's data attribute assign a property called refreshValue and give it a value like 1. And then when you need to refresh the component you just change the value. This might require you emitting an event from the PostCropper component to the parent and then incrementing refreshValue.

Justin Feakes
  • 380
  • 1
  • 7
  • so, i need to watch the key instead of the uploadImage? or there's no need to watch the key? – Khairul Habib Dec 18 '19 at 02:37
  • i've read about this before. i can understand what need to do with parent component. but what should we do with the child components? @Justin Feakes. because i'tried but it's nothing happens – Khairul Habib Dec 18 '19 at 02:54
  • `` and this is the increment function: ` updateImage(updatedImage) { this.latestImage = updatedImage; this.refreshCropper += 1; this.showCropper = false; },` – Khairul Habib Dec 18 '19 at 02:58
-1

i have another way which destroy the child component in parent component instead of destroy a variable. it's worked perfectly by using v-if method to destroy the imported components.

Khairul Habib
  • 452
  • 1
  • 12
  • 29