renderItem vue smartSelect with onClick

[Just for my own reference since there was no documented way to do this]

When using SmartSelect with Vue and the need to render a custom renderItem, those “raw” html are not vue reactive, so @click or the like wont work.

In my case I wanted to add the option of “New item” without the radio style at index 0. For that the smartSelect component requires the use of :smart-select-params like so:

<f7-list-item
          id="createItemSmartSelect"
          ....
          smart-select
          :smart-select-params="{ renderItem: renderItem }"
>
  <select name="fruits" @change="onChange">
            <option>New Category</option>
            <option
              v-for="(category, key) in itemCategories"
              :value="category"
              :key="key"
            >
              {{ category }}
            </option>
          </select>
.....
const renderItem = (item, index) => {
  if (index == 0) {
    return `
    <li  >
      <label onClick="createNewItemCategory()" class='item-radio item-radio-icon-start item-content' >
        <div class='item-inner'><div class='item-title'>${item.text}</div></div>
      </label>
    </li>`
  }
  return `
    <li>
      <label class='item-radio item-radio-icon-start item-content'>
        <input type='radio'  name="${item.inputName}" value='${item.value}'><i class='icon icon-radio'></i><div class='item-inner'><div class='item-title'>${item.text}</div></div>
      </label>
    </li>`
}

Now because the added item is not vue reactive, the click on that option must be done different (in lack of better way). To trigger my function using native JS, with the onClick handler the issue is that this is not scoped to the Vue instance. To workaround that, there is the need to create in the global window the function we need, and then pass to that closure a reference to our vue methods/function handlers.

As I’m using composition API:

const newCategory = () => {
  var newCategoryName = prompt('New Category')
  if (newCategoryName) {
    newItem.value.categories.push(newCategoryName)
    f7.smartSelect.close('#createItemSmartSelect .smart-select')
  }
}

//Export this function into the global, to be accessible by the smart custom render item raw html as native js function
window.createNewItemCategory = Object.freeze(newCategory)

This creates in the global function createNewItemCategory a reference to the vue method newCategory function.

Now the custom html select option can access it to trigger the new option function handler. All defined inside the same Vue instance. The only downside is really the global pollution and expose.

 <label onClick="createNewItemCategory()" ....>