Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use dynamic tailwind classes with JS switch statement and pass them correctly in Vue?

I am a beginner to Vue JS and I'm trying to create a function for assigning corresponding colours to the order statuses. I would like to use switch-statement to achieve this, that would grab the value of order status and pass it to the getStatusColour function(), like this:

const getStatusColour = (orderStatus) => {
    let statusColour = "";
    switch (orderStatus) {
        case "new": 
            statusColour = "bg-green-100 text-green-900";
            break;
        case "preparing": 
            statusColour =  "bg-yellow-400 text-yellow-900";
            break;
        case "ready":
            statusColour = "bg-blue-200 text-blue-800";
            break;
        case "delivered":
            statusColour = "bg-green-300 text-green-800";
            break;
        case "failed": 
            statusColour = "bg-red-400 text-red-900";
            break;
        default:
            statusColour = "bg-gray-100 text-gray-800"
    }
    return statusColour;
}

Then in the Index.vue file I have export default { getStatusColour }, I guess that's should be a mistake here.

And then in the template I call it like this:

<span :class="getStatusColour(order.status)">{{ order.status }}</span>

But I keep getting Uncaught (in promise) TypeError: _ctx.getStatusColour is not a function error. I'll appreciate any help here.

like image 214
Irina Pozdeeva Avatar asked Oct 22 '25 23:10

Irina Pozdeeva


1 Answers

As shown in the MDN docs: https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export#using_named_exports


Here is the whole github codebase.

utils/test.js

const getStatusColour = (orderStatus) => {
  let statusColour = ''
  switch (orderStatus) {
    case 'new':
      statusColour = 'bg-green-100 text-green-900'
      break
    case 'preparing':
      statusColour = 'bg-yellow-400 text-yellow-900'
      break
    case 'ready':
      statusColour = 'bg-blue-200 text-blue-800'
      break
    case 'delivered':
      statusColour = 'bg-green-300 text-green-800'
      break
    case 'failed':
      statusColour = 'bg-red-400 text-red-900'
      break
    default:
      statusColour = 'bg-gray-100 text-gray-800'
  }
  return statusColour
}

export { getStatusColour }

App.vue

<template>
  <div>
    <div :class="getStatusColour(order.status)">
      This div do have the correct: `bg-green-100 text-green-900` on it
    </div>
  </div>
</template>

<script>
import { getStatusColour } from './utils/test'

export default {
  data() {
    return {
      order: {
        status: 'new',
      },
    }
  },
  methods: {
    getStatusColour,
  },
}
</script>

Here is a github repo to show that your code is working great so far: https://github.com/kissu/so-compute-exported-function


How I do personally handle this kind of flow

callToAction.vue

<button
  class="flex items-center w-auto p-4 text-center ..."
  :class="[
    callToAction.types[color][variant],
    { 'opacity-50 cursor-not-allowed shadow-none': disabled },
  ]"
>
  Nice flexible button
</button>

<script>
export default {
props: {
  color: {
    type: String,
    default: 'primary',
  },
  variant: {
    type: String,
    default: 'enabled',
  },
  disabled: {
    type: Boolean,
    default: false,
  },
},

data() {
  return {
    callToAction: {
      types: {
        primary: {
          enabled: 'disabled:bg-primary-500 hover:bg-primary-700 bg-primary-500 text-primary-500',
          outlined: 'hover:bg-primary-a12 text-primary-500',
          reversed: 'text-primary-500',
        },
        secondary: {
          enabled: 'disabled:bg-secondary-500 hover:bg-secondary-700 bg-secondary-500 text-secondary-500',
          outlined: 'hover:bg-secondary-a12 text-secondary-500',
          reversed: 'text-secondary-500',
        },
        tertiary: {
          enabled: 'disabled:bg-tertiary-500 hover:bg-tertiary-700 bg-tertiary-500 text-tertiary-500',
          outlined: 'hover:bg-tertiary-a12 text-tertiary-500',
          reversed: 'text-tertiary-500',
        },
        bluegray: {
          enabled: 'disabled:bg-bluegray-500 hover:bg-bluegray-700 bg-bluegray-500 text-bluegray-500',
          outlined: 'hover:bg-bluegray-a12 text-bluegray-500',
          reversed: 'text-bluegray-500',
        },
        error: {
          enabled: 'disabled:bg-error-500 hover:bg-error-700 bg-error-500 text-error-500',
          outlined: 'hover:bg-error-a12 text-error-500',
          reversed: 'text-error-500',
        },
      },
    },
  }
}
</script>

Then, call it in other pages/components with something like:

<call-to-action color="tertiary" variant="reversed"></call-to-action>

Or let the defaults do it's job with color="primary", variant="enabled" and so on...

PS: adding validators to props could be nice, will be more friendly for the other developers working on the project, figuring out all the possible values that can be passed.

like image 194
kissu Avatar answered Oct 24 '25 12:10

kissu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!