visma-meglerfront / sweet-modal-vue

The sweetest library to happen to modals.
Other
757 stars 85 forks source link

Is it possible to open inside a rendered list? #89

Open baristaGeek opened 5 years ago

baristaGeek commented 5 years ago

Is it possible to do this?

  <li v-for="data in tableData" v-bind:key="data">
    <button v-on:click='openModal()'>{{data.date}}</button>
           <sweet-modal ref='modal'>
                {{data.name}}
           </sweet-modal>
  </li>

I'm getting a this.$refs.modal.open is not a function and I suspect that it is because thismust be used in some clever way in the function that opens the modal.

titusdecali commented 5 years ago

This might help: https://vuejsfeed.com/blog/modal-library-available-for-vue-js

pet1330 commented 5 years ago

I have yet to find a way of doing this. I have instead wrapped it in my own custom component, which has an open method that takes an object as a parameter. That way I can have a single modal that is mounted (but not shown) when the page loads and then each item in the list will set the modal as needed and then show it by calling open(data.data). It works quite well, as it means you only need one modal per type in the list, rather than per instance in the list.

    open(object_to_show = null) {
      if (object_to_show !== null) {
            this.title = object_to_show.title;
            this.message = object_to_show.message;
            // setup the modal as needed, etc...
      }
      this.$refs._modal.open();
    },
    formClosed() {
        this.$refs._modal.close();
        this.title = "";
        this.message = "";
        //etc, etc...
    }

Another catch is that you need to overwrite the close button in order to reset the modal each time it closes.

  <sweet-modal ref="_modal" :blocking="true" :hide-close-button="true">
    <div slot="title" class="sweet-title" style="padding-left: 0;">
      <h2 v-if="title">{{ this.title }}</h2>
      <h2 v-else>Default Title</h2>
      <div class="sweet-box-actions d-flex">
        <div class="sweet-action-close" @click="formClosed">
          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
            <path
              d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"
              fill="#292c34"
            />
          </svg>
        </div>
      </div>
    </div>
    <div>

        {{ message || "default message" }}
        <!-- MAIN BODY OF THE MODAL TO CUSTOMISE -->

    <div>

</sweet-modal>

It feels a bit hacky, but the only other way I could make it work was to have a modal instance per item in a list. If you find a better way of doing this, please let me know :)

AlbertoTorre commented 5 years ago
<div>
            <li v-for="data in tableData" :key="data.id">
                <button @click.prevent='open(data.name)'>{{data.date}}</button>
            </li>
            <sweet-modal ref='modal'>
                    {{ name }}
            </sweet-modal>
</div>
<script>
export default {
    name:'example',
    data: () => {
        name:{type:String, default:''}
    },
    methods:{
        open () {
            this.name = name
            this.$refs.modal.open()
        }
    }
}
<script>
f3yisayo commented 5 years ago

I was able to do this by putting the modal outside the list's loop first, then pass in the object containing an item on the list, in this case item:

<li v-for="item in tableData" :key="item">
   <button v-on:click='openModal(item)'>{{item.date}}</button>
</li>

<sweet-modal ref='modal'> {{item.name}} </sweet-modal>

Create a data property to hold the item on the list, then pass down the item to the OpenModal method:

<script>
export default {
    data: () => {
        item: {}
    },
   methods: {
       openModal(item) {
          this.item = item
          this.$refs.modal.open()
      }
  }
}
</script>