简体   繁体   中英

Vue: Get data from parent in <slot>

I don't know if what I want is possible in the way I want to do it. I'm using this Vue plugin for modals: https://www.npmjs.com/package/vue-js-modal

I have a component called ModalButton that is responsible for triggering the modal:

<modal-button :modal-data="{{  collect(['account' => $account])  }}" modal-name="leave-account">Leave Account</modal-button>

As you can see, I'm sending :modal-data as props.

The ModalButton component is the following:

<template>
  <button @click.prevent="show" type="button" class="px-3 py-2 bg-gray-200 font-bold text-gray-700 ">
    <slot></slot>
  </button>
</template>

<script>
// @ is an alias to /src

export default {

  name: 'ModalButton',
  data() {
      return {

      }
  },

  props: {
    modalName: String,
    modalData: Object
  },

  methods: {
    show () {
      this.$modal.show(this.modalName, this.modalData);
    },
    hide () {
      this.$modal.hide(this.modalName);
    }
  }
}
</script>

You can see on the show method which comes from the plugin is sending that data to the modal

this.$modal.show(this.modalName, this.modalData);

In my blade template (i'm using laravel), I have the <modal> :

<modal name="leave-account" class="text-center">
    <div class="flex items-center justify-center h-full p-6">
        <div>
            <div>
                <div class="text-3xl font-bold mb-2">Are you sure?</div>
                <p>If you leave this account, you won't be able to join back unless invited again. </p>
            </div>
            <footer class="flex items-center justify-end mb-24 mt-auto">
                <button class="px-3 py-2 bg-gray-200 font-bold text-gray-700 mr-3">Cancel</button>
                <ajax-button 
                class-list="px-3 py-2 bg-primary text-white font-bold"
                :route=@{{SOMEHOW ACCESS MODAL DATA}}
                method="delete">
                Yes, leave account
                </ajax-button>
            </footer>
        </div>
    </div>
</modal>

Inside my modal, I have another component called AjaxButton which allows me to have a reusable button that handles ajax requests.

I need a way of accessing the modal data that was passed to the modal. I'd like not to have to create an additional specific modal component to handle this.

Is this possible?

Specifically what the :route prop needs to send is the Account since my route requires model binding. ie it'll look something like /accounts/leave/53

Edit:

So I can do this:

<button @click="$modal.hide('leave-account')" class="px-3 py-2 bg-gray-200 font-bold text-gray-700 mr-3">Cancel</button>

(that's right above my <ajax-button> )

So clearly I'm able to access the $modal properties / methods. So there has to be a way to accomplish what I want

You can use a simpler modal:

<modal-button v-model="showModal">
Leave Account
</modal-button>
<modal v-model="showModal" caption="Leave Account">
{{  collect(['account' => $account])  }}
</modal>

Then modal-button will look like this:

<template>
  <button @click.stop="$emit('input',true)" type="button" class="px-3 py-2 bg-gray-200 font-bold text-gray-700 ">
    <slot/>
  </button>
</template>

<script>
export default
{
  name: 'ModalButton',
  props:
  {
    value:
    {
      type: Boolean,
      default: false
    }
  }
}
</script>

and the modal component will be:

<template>
  <transition name="modal">
    <div class="modal_overlay" @click="close" v-if="value">
      <div class="modal_content" style="overflow: auto;" @click.stop>
        <div class="modal_title">{{ caption }} <div class="modal_close" @click="close">&#10006;</div></div>
        <slot/>
      </div>
    </div>
  </transition>
</template>

<script>

export default
{
  props: 
  {
    value:
    {
      type: Boolean,
      default: false
    },
    caption:
    {
      type: String,
      default: ''
    },

  created()
  {
    document.addEventListener('keydown', this.modal_escape, false);
  },
  beforeDestroy()
  {
    document.removeEventListener('keydown', this.modal_escape, false);
  },
  methods:
    {
      close()
      {
        this.$emit('input', false);
      },
      modal_escape(event)
      {
        var e = event || window.event;
        if(this.value && e.keyCode == 27)
        {
          this.close();
          // All good browsers…
          if (e.preventDefault) e.preventDefault();
          // …and IE
          if (e.returnValue) e.returnValue = false;
          return false;
        }
      }
    }
}
</script>

<style>
  .modal_overlay
  {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 25;
    text-align: initial;
    background-color: rgba(0,0,0,0.75);
  }

  .modal_content
  {
    position: relative;
    display: inline-block;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
    background-color: white;
    border: 2px solid #000;
    border-radius: 5px;
    max-width: 90vw;
    max-height: 90vh;
  }

  .modal_title
  {
    text-align: center;
    background-color: #F27935;
    color: white;
    line-height: 1.65;
    padding-left: 6px;
  }

  .modal_close
  {
    float: right;
    display: inline-block;
    cursor: pointer;
    padding: 0 5px 0 4px;
  }

  .modal_close:hover
  {
    color: white;
    background-color: #00B4FF;
  }

  .modal-enter-active
  {
    transition: all .4s ease;
  }

  .modal-leave-active
  {
    transition: all .2s cubic-bezier(1.0, 0.5, 0.8, 1.0);
  }

  .modal-enter, .modal-leave-to
  {
    transform: translateX(10px);
    opacity: 0;
  }
</style>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM