utdev
utdev

Reputation: 4102

Vue.js dialog/modal closes on parent component

I am trying to open my CanvasPreview Component in another component but it fails, first, it quickly shows the dialog/modal afterward it gets hidden again if I open the Vue Dev tool the showCanvasPreview is set to false if I manually edit it in my console to true the modal gets shown. So I guess that it gets set to false again, but I can't see why.

This is the dialog/modal component:

<template>
    <v-dialog
        v-model="show"
    >
        <v-card>
            <v-card-actions>
                <v-container grid-list-md text-xs-center>
                    <v-layout row wrap>

                    </v-layout>
                </v-container>
            </v-card-actions>
        </v-card>
    </v-dialog>
</template>

<script>
import CanvasPreviewSourceUpload from './CanvasPreviewSourceUpload';

export default {
    components: {
        'canvas-preview-source-upload': CanvasPreviewSourceUpload
    },

    props: {
        imgSrc: String,
        visible: Boolean   
    },

    computed: {
        show: {
            get () {
                return this.visible;
            },
            set (visible) {
                if (!visible) {
                    this.$emit('closePreview');
                }
            }
        }
    },
}
</script>

And in my parent component I call the preview component like this:

<template>
    <div>
        //... some more html
        <div id="canvas-body">
            <canvas id="pdf-render"></canvas>
            <canvas id="selectCanvas"
                @mousedown="markElementOnMouseDown"
                @mousemove="updatePreview"
                @mouseup="markElementOnMouseUp">
            </canvas>
        </div>

       <canvas-preview
            :imgSrc="this.targetImage.src"
            :visible="showCanvasPreview"
            @closePreview="showCanvasPreview=false">
        </canvas-preview>
    </div>
</template>


<script>
import CanvasPreview from '@/js/components/CanvasPreview';

export default {
    components: {
        'canvas-preview': CanvasPreview
    },

    props: {
        'name': String
    },

    data: () => ({
        showCanvasPreview: false,
        ...
    }),

    methods: {
        markElementOnMouseUp (event) {
            this.isDragging = false;
            this.targetImage.src = this.clipCanvas.toDataURL();
            this.targetImage.style.display = 'block';

            this.showCanvasPreview = true;
            console.log("mouseup: " + this.showCanvasPreview);
        },
    }
</script>

Upvotes: 0

Views: 1175

Answers (2)

Matt Oestreich
Matt Oestreich

Reputation: 8538

Something like this should allow you to open a v-dialog from a separate component..

If you supply a CodePen or CodeSandbox with your code in it, we would be able to better assist you.

[CodePen mirror]

const dialog = {
  template: "#dialog",
  props: {
    value: {
      type: Boolean,
      required: true
    },
  },
  computed: {
    show: {
      get() {
        return this.value;
      },
      set(value) {
        this.$emit("input", value);
      }
    }
  },
};

const dialogWrapper = {
  template: "#dialogWrapper",
  components: {
    appDialog: dialog,
  },
  data() {
    return {
      isShown: false,
    }
  }
}

new Vue({
  el: "#app",
  components: {
    dialogWrapper
  }
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />

<div id="app">
  <v-app>
    <v-content>
      <dialog-wrapper/>
    </v-content>
  </v-app>
</div>

<script type="text/x-template" id="dialog">
  <v-dialog v-model="show">
    <v-card>
      <v-card-actions pa-0>
        <v-spacer/>
        <v-btn dark small color="red" @click="show = false">Close</v-btn>
        <v-spacer/>
      </v-card-actions>
      <v-card-title class="justify-center">
        <h2>
          Hello from the child dialog
        </h2>
      </v-card-title>
    </v-card>
  </v-dialog>
</script>

<script type="text/x-template" id="dialogWrapper">
  <div>
    <h1 class="text-xs-center">I am the wrapper/parent</h1>
    <v-container>
      <v-layout justify-center>
        <v-btn color="primary" dark @click.stop="isShown = true">
          Open Dialog
        </v-btn>
      </v-layout>
    </v-container>
    <app-dialog v-model="isShown"></app-dialog>
  </div>
</script>

Upvotes: 0

dimas
dimas

Reputation: 389

Try this one

    <v-dialog
        v-model="show"
    >
        <v-card>
            <v-card-actions>
                <v-container grid-list-md text-xs-center>
                    <v-layout row wrap>
                        <canvas-preview-source-upload 
                            :imgSrc="imgSrc"
                            @close.stop="show=false">
                        </canvas-preview-source-upload>
                    </v-layout>
                </v-container>
            </v-card-actions>
        </v-card>
    </v-dialog>
</template>

<script>
import CanvasPreviewSourceUpload from './CanvasPreviewSourceUpload';

export default {
    components: {
        'canvas-preview-source-upload': CanvasPreviewSourceUpload
    },
    data: ()=> ({
      show: false
    }),
    props: {
        imgSrc: String,
        visible: Boolean   
    }, 
    watch: {
      show(isShow){
        if (!isShow) {
            this.$emit('closePreview');
        }
      }
      visible(isVisible) {
        this.show = isVisible;
      }
    }
}
</script>```

Upvotes: 0

Related Questions