0

I have this simple registration page:

<template>
  <div class="login">

    <div class="login-content">
      <h1 @click="redirect('/')">Logo</h1>
    </div>

    <div class="login-header">
      <p class="paragraph-small right">Already have account?
        <span class="paragraph-small pointer link" @click="redirect('/login')">Log in!</span>
      </p>
    </div>

    <div class="login-inputs">
      <div class="login-inputs-container">
        <h1>Sign up</h1>
        <Input :error="error" :title="'Email'" :type="'email'" :value="email" />
        <Input :error="error" :title="'Password'" :type="'password'" :value="password" />
        <Input :error="error" :title="'Repeat password'" :type="'password'" :styles="'padding-bottom: 10px'" :value="passwordRepeat" />
        <Checkbox :value="tac" :label="`I have read and accepted <a href='/'>terms and conditions.</a>`" />
        <Button :label="'Sign up'" :clickon="register" />
        <p v-if="error">Passwords have to match!</p>
      </div>
    </div>

  </div>
</template>

<script>
import { register } from "~/api";
import { mapGetters, mapState, mapActions, mapMutations } from 'vuex';
import Input from "~/components/Input";
import Button from "~/components/Button";
import Checkbox from "~/components/Checkbox";
export default {
  name: "register",
  components: {
    Input,
    Button,
    Checkbox
  },
  watch: {
    password() { this.error = (this.password !== this.passwordRepeat) && (this.password !== null && this.passwordRepeat !== null) },
    passwordRepeat() { this.error = (this.password !== this.passwordRepeat) && (this.password !== null && this.passwordRepeat !== null) }
  },
  computed: {
    ...mapGetters({
      email: 'register/getEmail',
      password: 'register/getPassword',
      passwordRepeat: 'register/getPasswordRepeat',
      status: 'register/getStatus',
      error: 'register/getError',
      tac: 'register/getTac'
    })
  },
  methods: {
    redirect(path) {
      this.$router.push({ path })
    },
    async register() {
      console.log(this.tac, this.password, this.passwordRepeat, this.email)
    }
  }
}
</script>

<style lang="scss">
@import "../assets/css/login";
</style>

As you can see, there are 4 fields where I want to change value - 3 Input and 1 Checkbox. When I provide data and click button in console I get the default values, I was trying to do something with mutations and actions, but it doesn't work.

Can it be because I use my components, not default?

Also, here is my store store/register.js

export const state = () => ({
  email: null,
  password: null,
  passwordRepeat: null,
  status: null,
  error: false,
  tac: false
})

export const mutations = {
  setEmail(state, value) { state.email = value },
  setPassword(state, value) { state.password = value },
  setPasswordRepeat(state, value) { state.passwordRepeat = value },
  setStatus(state, value) { state.status = value },
  setError(state, value) { state.error = value },
  setTac(state, value) { state.tac = value }
}

export const actions = {
  fetchEmail(ctx, value) { ctx.commit('setEmail', value) },
  fetchPassword(ctx, value) { ctx.commit('setPassword', value) },
  fetchPasswordRepeat(ctx, value) { ctx.commit('setPasswordRepeat', value) },
  fetchStatus(ctx, value) { ctx.commit('setStatus', value) },
  fetchError(ctx, value) { ctx.commit('setError', value) },
  fetchTac(ctx, value) { ctx.commit('setTac', value) },
}

export const getters = {
  getEmail(state) { return state.email },
  getPassword(state) { return state.password },
  getPasswordRepeat(state) { return state.passwordRepeat },
  getStatus(state) { return state.status },
  getError(state) { return state.error },
  getTac(state) { return state.tac },
}

If problem is that I use not default tags, but my components with props, here is Checkbox component:

<template>
  <div class="checkbox-container">
    <label class="container">
      <input type="checkbox" :value="innerValue" @input="onInput">
      <span class="checkmark"></span>
    </label>
    <p class="checkbox-paragraph" v-html="label" />
  </div>
</template>

<script>
export default {
  props: {
    label: {
      type: String,
      default: ''
    },
    value: {
      type: Boolean,
      default: false
    }
  },
  name: "Checkbox",
  watch: {
    value(value) {
      this.innerValue = value
    },
    innerValue(value) {
      this.$emit('input', value)
    }
  },
  data() {
    return {
      innerValue: this.value
    }
  },
  methods: {
    onInput() {
      this.$nextTick(() => {
        this.innerValue = !this.innerValue
      })
    }
  }
}
</script>
3
  • Are you trying to change the values or you just want to get the values coming from the store? Because I don't see how are you handling the emit from checkbox. You just emit it but where are you using it to change the value? Commented Feb 16, 2022 at 18:22
  • Actually, I want to change values. I have never worked with vuex in Nuxt.js project, so, I don't really know on how to do that. Commented Feb 16, 2022 at 18:24
  • It would be nice if you create a little project for your problem in stackblitz. That way I can help you. Commented Feb 16, 2022 at 18:28

2 Answers 2

1

One way that can help you change the value of your checkbox is like this.

Checkbox Component:

<template>
  <div class="checkbox-container">
    <label class="container">
      <input type="checkbox" @change="$emit('checkbox', value)" />
      <span class="checkmark"></span>
    </label>
  </div>
</template>

<script>
export default {
  name: 'Checkbox',
  data() {
    return {
      value: false,
    }
  },
}
</script>

Now inside your register page you can use the checkbox component in template like this:

<Checkbox @checkbox="checkboxChanged" />

Now in the same page and in method section add this method:

checkboxChanged(event) {
      this.$store.dispatch('register/fetchTac', event)
    },
},

This way, when the value of checkbox changes you can have the changed value in your store too and get it with mapGetter. You can do the same to your inputs.

Sign up to request clarification or add additional context in comments.

Comments

0

Okay, here is my working answer, I don't really know if it's correct, but it doesn't contain any errors or warnings:

<template>
  <div class="login">

    <div class="login-content">
      <h1 @click="redirect('/')">Logo</h1>
    </div>

    <div class="login-header">
      <p class="paragraph-small right">Already have account?
        <span class="paragraph-small pointer link" @click="redirect('/login')">Log in!</span>
      </p>
    </div>

    <div class="login-inputs">
      <div class="login-inputs-container">
        <h1>Sign up</h1>
        <Input :error="error" :title="'Email'" :type="'email'" v-model="email" />
        <Input :error="error" :title="'Password'" :type="'password'" v-model="password" />
        <Input :error="error" :title="'Repeat password'" :type="'password'" :styles="'padding-bottom: 10px'" v-model="passwordRepeat" />
        <Checkbox v-model="tac" :label="`I have read and accepted <a href='/'>terms and conditions.</a>`" />
        <Button :label="'Sign up'" :clickon="register" />
        <p v-if="error">Passwords have to match!</p>
      </div>
    </div>

  </div>
</template>

<script>
import { register } from "~/api";
import { mapGetters, mapState, mapActions, mapMutations } from 'vuex';
import Input from "~/components/Input";
import Button from "~/components/Button";
import Checkbox from "~/components/Checkbox";
export default {
  name: "register",
  components: {
    Input,
    Button,
    Checkbox
  },
  watch: {
    ...mapActions(['fetchTac', 'fetchError', 'fetchStatus', 'fetchPasswordRepeat', 'fetchPassword', 'fetchEmail']),
    password() { this.error = (this.password !== this.passwordRepeat) && (this.password !== null && this.passwordRepeat !== null) },
    passwordRepeat() { this.error = (this.password !== this.passwordRepeat) && (this.password !== null && this.passwordRepeat !== null) }
  },
  computed: mapGetters(['getError', 'getEmail', 'getPassword', 'getPasswordRepeat', 'getStatus', 'getTac']),
  data() {
    return {
      email: null,
      password: null,
      passwordRepeat: null,
      status: null,
      error: false,
      tac: false
    }
  },
  methods: {
    redirect(path) {
      this.$router.push({ path })
    },
    async register() {
      console.log(this.passwordRepeat, this.password, this.email, this.tac)
    }
  }
}
</script>

But I still have one problem, as you can see, I have getters and data at the same time, I can actually remove data, but it will cause such warning:

Property or method "propname" 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

It will work, but I will have this warning.

EDIT

I solved this problem that way:

computed: {
    error: {
      get() { return this.$store.getters.getError },
      set(value) { this.$store.commit('setError', value) }
    },
    email: {
      get() { return this.$store.getters.getEmail },
      set(value) { this.$store.commit('setEmail', value) }
    },
    password: {
      get() { return this.$store.getters.getPassword },
      set(value) { this.$store.commit('setPassword', value) }
    },
    passwordRepeat: {
      get() { return this.$store.getters.getPasswordRepeat },
      set(value) { this.$store.commit('setPasswordRepeat', value) }
    },
    status: {
      get() { return this.$store.getters.getStatus },
      set(value) { this.$store.commit('setStatus', value) }
    },
    tac: {
      get() { return this.$store.getters.getError },
      set(value) { this.$store.commit('setTac', value) }
    }
  },
  // data() {
  //   return {
  //     email: null,
  //     password: null,
  //     passwordRepeat: null,
  //     status: null,
  //     error: false,
  //     tac: false
  //   }
  // },

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.