Search code examples
javascriptvue.jsvuejs2sweetalert2

How to use v-for in SweetAlert2 html output


I'm trying to show the following template in an alert with vue-sweetalert2:

<input v-model="name" class="swal2-input">

<select v-model="parent" name="parent" class="form-control">
  <option v-for="category in categories" v-bind:value="category.id">
    {{category.name}}
  </option>
</select>

I do not have any problem in a normal template, but I don't know how to use this in SweetAlert2.

I tried this code:

this.$swal({
  text: 'edit child',
  html:
   '<input v-model="name" class="swal2-input">' +
   `<select v-model="parent" name="parent" class="form-control">
      <option value="">nothing</option>
      <option v-for="category in categories" v-bind:value="category.id">
        {{category.name}}
      </option>
    </select>`,
  showCancelButton: true,
  confirmButtonText: 'edit',
  cancelButtonText: 'cancel',
  showCloseButton: true,
})

but it shows me nothing.


Solution

  • Since the HTML passed to SweetAlert2 is not handled by Vue, the template mechanisms (including v-for and v-model) would not be available, so you would have to manually create the template with JavaScript. Specifically, you would replace:

    html: `<input v-model="name" class="swal2-input">
    <select v-model="parent" name="parent" class="form-control">
      <option v-for="category in categories" v-bind:value="category.id">{{category.name}}</option> ...`
    

    with:

    html: `<input id="my-input" value="${this.name}" class="swal2-input">
    <select id="my-select" value="${this.parent}" name="parent" class="form-control">
      ${this.categories.map(cat => `<option value="${cat.id}">${cat.name}</option>`)} ...`
    

    Note the <input> and <select> were given IDs so that we can fetch the values on "pre-confirmation" of the alert:

    const {value} = this.$swal({
      preConfirm: () => [
        document.getElementById("my-input").value,
        document.getElementById("my-select").value
      ]
    });
    console.log(value[0]); // value of my-input
    console.log(value[1]); // value of my-select
    

    demo