Search code examples
vue.jsvuejs3vue-composition-apivue-script-setup

VueJS passing parameter to bound property


I want to track the state of several buttons without having a tracker variable and function for each.

So I want to pass a parameter through to a computed property, something like this:

<div class="grid grid-cols-5 text-sm my-3">
  <div @click="toggleShow('weapon')" :class="showStyle('weapon')">Weapon</div>
  <div @click="toggleShow('armor')" :class="showStyle('armor')">Armor</div>
  <div @click="toggleShow('ring')" :class="showStyle('ring')">Ring</div>
  <div @click="toggleShow('amulet')" :class="showStyle('amulet')">Amulet</div>
  <div @click="toggleShow('horse')" :class="showStyle('horse')">Horse</div>
</div>

However, neither of these two approaches is working:

const showStyle = (category: string) =>
  computed(() => {
    if (show.value.get(category)) {
      return "bg-green-700";
    } else {
      return "bg-red-700";
    }
});

// I am not redeclaring in my real code, this is just in the same block for demonstration
// gives error $setup.showStyle is not a function
const showStyle = computed((category) => {
  if (show.value.get(category)) {
    return "bg-green-700";
  } else {
    return "bg-red-700";
  }
});

I'm using a Map to track each flag:

const show = ref(new Map());
show.value.set("weapon", true);
show.value.set("armor", true);
show.value.set("ring", true);
show.value.set("amulet", true);
show.value.set("horse", true);
show.value.set("potion", false);

And the toggle function appears to be working at swapping the values:

function toggleShow(category: string) {
  alert(show.value.get(category));
  show.value.set(category, !show.value.get(category));
}

What I want to avoid is having a separate computed() value for each category and rather pass in the parameter.

Is this possible? How?


Solution

  • You could parameterize the computed property by return a function from it like:

    const showStyle = computed(()=> (category) => {
      if (show.value.get(category)) {
        return "bg-green-700";
      } else {
        return "bg-red-700";
      }
    });
    
    

    This works fine but it doesn't have extra benefits than a standard function :

    const showStyle = (category) => {
      if (show.value.get(category)) {
        return "bg-green-700";
      } else {
        return "bg-red-700";
      }
    }
    

    You could check this answer from Estus Flask to get more explanation.