How to use enums (or const) in VueJS?

Javascriptvue.js

Javascript Problem Overview


I feel like an idiot for having to ask about something so seemingly simple, but I'm trying to figure out how to use "enums" in VueJS. Currently, in a file called LandingPage.js I have this bit of code:

const Form = {
  LOGIN: 0,
  SIGN_UP: 1,
  FORGOT_PASSWORD: 2,
};

function main() {
  new Vue({
    el: "#landing-page",
    components: {
      LoginForm,
      WhoIsBehindSection,
      WhatIsSection,
      Form,
    },
    data () {
      return {
        form: Form.LOGIN,
      };
    },
    template: `
    <div>
      <LoginForm v-if="form === Form.LOGIN"></LoginForm>
      <WhatIsSection></WhatIsSection>
      <WhoIsBehindSection></WhoIsBehindSection>
    </div>
    `
  });
}

It is the conditional v-if="form === Form.LOGIN" that is failing with the error messages:

> - Property or method "Form" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.

> - Cannot read property 'LOGIN' of undefined

Just so you guys know without the conditional everything is working, and if I were to put this bit in the template

<p>{{ form }}</p>

it will print 0 on the screen. Though, putting this in the template

<p>{{ Form.LOGIN }}</p>

Will not result in it printing 0 on the screen. So I just cannot for the life of me figure out why it will not accept Form.LOGIN.

 

The Answer

I did add it to components, but never did I think of adding it to data. Happy that it's working now. :)

    data () {
      return {
        form: Form.LOGIN,
        Form, // I had to add this bit
      };
    },

Thank you MarcRo

Javascript Solutions


Solution 1 - Javascript

If you are using Vue in Typescript, then you can use:

import { TernaryStatus } from '../enum/MyEnums';  
  
export default class MyClass extends Vue {

      myVariable: TernaryStatus = TernaryStatus.Started;

      TernaryStatus: any = TernaryStatus;  

 }

and then in Template you can just use

<div>Status: {{ myVariable == TernaryStatus.Started ? "Started It" : "Stopped it" }}</div>

Solution 2 - Javascript

You can use https://stackoverflow.com/a/59714524/3706939.

const State= Object.freeze({ Active: 1, Inactive: 2 });
export default {
  data() {
    return {
      State,
      state: State.Active
    };
  },
  methods: {
    method() {
      return state==State.Active;
    }
  }
}

Solution 3 - Javascript

You only have access to properties of the Vue instance in your template. Just try accessing window or any global in your template, for example.

Hence, you can access {{ form }} but not {{ Form.LOGIN }}.

A wild guess is that it has something to do with how Vue compiles, but I don't know enough about the internals to answer this.

So just keep declaring all the properties you wish to use in your template in your Vue instance (usually as data).

Solution 4 - Javascript

You can enclose enum into class. All your data, the state, the enum variants would be in one place. The same about behaviours, so you will call form.isLogin() rather than form === Form.LOGIN and form.setLogin() rather than form = Form.Login.

The class to generate enums:

class Fenum {
  constructor(start, variants) {
    this.state = start;

    variants.forEach(value => {
      const valueC = value.charAt(0).toUpperCase() + value.slice(1);
      this['is' + valueC] = () => this.state === value;
      this['set' + valueC] = () => this.state = value;
    })
  }
}

Example of usage:

function main() {
  new Vue({
    el: "#landing-page",
    components: {
      LoginForm,
      WhoIsBehindSection,
      WhatIsSection,
      Form,
    },
    data () {
      return {
        form: new Fenum("login", ["login", "signUp", "forgotPassword"]),
      };
    },
    template: `
    <div>
      <LoginForm v-if="form.isLogin()"></LoginForm>
      <WhatIsSection></WhatIsSection>
      <WhoIsBehindSection></WhoIsBehindSection>
    </div>
    `
  });
}

Vue observe nested objects, so each call of a set method (from.setLogin(), form.setSignUp(), ...) will trigger updates of the component as it should be.

The generated object from this example:

enter image description here

Solution 5 - Javascript

You can use $options instead of $data https://vuejs.org/v2/api/#vm-options

Solution 6 - Javascript

The easiest way!

in main.js

const enumInfo = {
  SOURCE_TYPE: {
    WALLET: 1,
    QR: 2
  }
}

Vue.prototype.enumInfo = enumInfo

index.vue

{{enumInfo}}

Solution 7 - Javascript

You can use Proxy to create object which throw runtime errors if someone will read non-defined value or try to add new value - here is createEnum (and use it in data() section)

function createEnum(name,obj) {
  return new Proxy(obj, {
    get(target, property) {
        if (property in target) return target[property];
        throw new Error(`ENUM: ${name}.${property} is not defined`);
    },
    set: (target, fieldName, value) => {
      throw new Error(`ENUM: adding new member '${fieldName}' to Enum '${name}' is not allowed.`);
    }
  });
}
  

// ---------------
// ----- TEST ----
// ---------------

const Form = createEnum('Form',{
  LOGIN: 0,
  SIGN_UP: 1,
  FORGOT_PASSWORD: 2,
});

// enum value exists
console.log(Form.LOGIN);

// enum value not exists
try{ console.log(Form.LOGOUT) } catch(e){ console.log(e.message)}

// try to add new value
try{ Form.EXIT = 5 } catch(e){ console.log(e.message)}

for string-like Enums where values are equal to keys you can use following helper

export function createEnumArr(name='', values=[]) {
  let obj = {};
  values.forEach(v => obj[v]=v);
  return createEnum(name,obj);
}

const Form = createEnumArr('Form',[
      "LOGIN",
      "SIGN_UP",
      "FORGOT_PASSWORD",
]);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionG. ThorsenView Question on Stackoverflow
Solution 1 - JavascriptMaheshView Answer on Stackoverflow
Solution 2 - JavascriptRoohi AliView Answer on Stackoverflow
Solution 3 - JavascriptMarcRoView Answer on Stackoverflow
Solution 4 - JavascriptAndriy KubaView Answer on Stackoverflow
Solution 5 - JavascriptThai Nguyen HungView Answer on Stackoverflow
Solution 6 - JavascriptansonView Answer on Stackoverflow
Solution 7 - JavascriptKamil KiełczewskiView Answer on Stackoverflow