Using vue component in sweetalert2 content
Asked Answered
B

3

10

I have a few plain Sweetalert2 modals in a Vue project. I want to use a custom component inside an alert. For example:

<template>
  <h1>Hello {{name}}</h1>
</template>
<script>
module.exorts: {
  props: ["name"]
}
</script>

my_template.vue

And, in my sweetalert modal:

swal({
  titleText: "Hi",
  html: '<my-template name="hello"></my-template>'
});

I'm not sure if this is even possible or how to do it.

Brunhilde answered 8/2, 2018 at 10:35 Comment(0)
F
6

Technically it looks possible:

Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})

new Vue({
  el: '#modal',
  beforeCreate:  swal({
    titleText: "Hi",
    html: '<div id="modal"><my-component></my-component></div>'
  })
})

But you may want to wrap it in a function. Take a look at my fiddle:

JS Fiddle

It's just an idea, for me it doesn't look good, but still working. Also I have to mention, that you will create new instance of vue every time you open your dialog this way.

Option 2 from comment to my answer:

Vue.component('my-component', {
    template: '<div>A custom component!</div>'
})    

swal({
    html: "<my-component></my-component>"
})
  
new Vue({
    el: swal.getHtmlContainer()
})  
 

Fiddle

Francisco answered 8/2, 2018 at 11:12 Comment(8)
or, even better: html: '<my-component></my-component>', and then new Vue({ el: swal.getContent() })Gallager
@LimonMonte thanks for an idea. I've added it to my answer, if you don't mind.Francisco
@KirillStepanov in realistic situation, our apps are full of data binding everywhere. This solution is about creating a new Vue object and make it render $swal.html, but the data binding won't work.... :( By the way, Limon Monte is the owner of sweetalert2.Amorous
@JustinMoh I agree, but we don't know context of question. I think passing properties in vue instance to render component is still possible. But I have no idea why not to use just template literal. Don't see any benefit in using vue for this.Francisco
@KirillStepanov what i'm currently using html: '<div id="swalHtml"></div>', then in onBeforeOpen:, use let ComponentClass = Vue.extend(MyComponent); let instance = new ComponentClass({ propsData: { item: this.item } }) to extend the vue component in the context, then mount it onto dom instance.$mount(); document.getElementById('swalHtml').appendChild(instance.$el).Amorous
The second fiddle will only work if you change it to use "swal.fire({...Duello
I'm trying to use a prop to pass a variable but it's not working..Kerrison
@Kerrison ensure you're using propsData and not propsEzechiel
R
2

You can render and hide the content inside your app:

<div id="swalHTML" style='display: none'>
  <my-template name="hello"></my-template>
</div>

Then pass the element's innerHTML to the alert:

let el = document.getElementById('swalHTML')
swal({
  html: el.innerHTML
});
Reduplication answered 31/12, 2020 at 7:47 Comment(0)
O
0

I have managed to make it work as follows:

I include all the logic of the template between backticks: ` `

you will also need edit the vue.config.js file and add inside the configurewebpack object add this: 'vue$':'vue/dist/vue.esm.js'

configureWebpack: {
resolve: {
  alias: {
    'src': resolveSrc('src'),
    'chart.js': 'chart.js/dist/Chart.js',

    // add this line for include components inside swal alert
    'vue$':'vue/dist/vue.esm.js'
  }
 }
}

Once this is done you must relaunch the project "npm run dev"

This is my complete example, tested and working

openSweet() {
  Vue.component('my-comp', {
      template: `
            <div class="card-content">
              <div class="span2">
                    <div class="col-sm-6 col-md-2 col-lg-3">
                        <div class="row">
                          <div style="margin-top: 6px;" >
                            <p-switch v-model="switchTrip.state" type="primary" 
on-text="ON" off-text="OFF" style="justify-content:center"></p-switch>
                            <h5 class="card-title" style="margin-left: 
25px;">Recorridos</h5>
                          </div>
                        </div>

                        <div class="row">
                          <div style="margin-top: 6px;" >
                            <p-switch v-model="switchVel.state" type="primary" 
on-text="ON" off-text="OFF" style="justify-content:center"></p-switch>
                            <h5 class="card-title" style="margin-left: 
25px;">Velocidad</h5>
                          </div>
                        </div>

                    </div>
              </div>
              <div class="span2">
                    <div class="col-sm-6 col-md-4 col-lg-3">
                        <div class="row">
                          <div >
                            <input type="search" class="form-control input-sm" 
placeholder="km / h" v-model="vmax">
                            <h5 class="card-title">Vel. Max</h5>
                          </div>
                        </div>

                        <div class="row">
                          <div>
                            <input type="search" class="form-control input-sm" 
placeholder="minutos" v-model="tol">
                            <h5 class="card-title">Tolerancia</h5>
                          </div>
                        </div>
                    </div>
              </div>
            </div>
      `,
    data () {
      return {
        switchVel: {
          state: false
        },
        switchEvent: {
          state: false
        },
        switchTrip: {
          state: false
        },
        search: '',
        vmax: '',
        tol: ''
      }
    },
    components: {
        [Button.name]: Button,
        Card,
        PSwitch
    }
  })
  new Vue({
    el: '#modal',
    beforeCreate:  () => {
      swal({
        titleText: "Descarga de Reportes",
        showCancelButton: true,
        cancelButtonText: 'Cancelar',
        confirmButtonText: 'Descargar',
        // confirmButtonAriaLabel: 'glyphicon glyphicon-ok-sign',
        // cancelButtonAriaLabel: 'glyphicon glyphicon-remove-sign',
        confirmButtonColor: '#3085d6',
        cancelButtonColor: '#d33',
        width: 800,
        html: '<div id="modal"><my-comp></my-comp></div>'
      })
    }
  })
}

I hope it helps you

Regards

Officious answered 8/10, 2019 at 16:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.