Create App With Django-Rest-Framework and Vue.js (Vuetify), Part III

In the third part I will write how to create the form described in part II in the frontend. All code is available in the git hub repository.

Create Vue.js project:

vue create gcode_frontend

Vue.js  has two beautiful UI-frameworks (there are many more, but these are my favorites). Vuetify and Bootstrap-Vue, Vuetify for build UI with a Material Design and Bootstrap-Vue for build UI with Bootstrap design. Vuetify more suitable for build UI with help already exists components and Bootstrap-Vue for more individual design. In this project I will use Vuetifly.

Add Vuetifly in Vue.js project:

vue add vuetify

This command will make changes to your initial project on Vue.js.

Need to create a configuration file (vue.config.js) at the root of the project some such content:

module.exports = {
  publicPath: "http://0.0.0.0:8080/",
  outputDir: "./dist/",
  
  transpileDependencies: [
    'vuetify'
  ],

  chainWebpack: (config) => {
    config.devServer
      .public("http://127.0.0.1:8080")
      .host("127.0.0.1")
      .port(8080)
      .hotOnly(true)
      .watchOptions({ poll: 1000 })
      .https(false)
      .disableHostCheck(true)
      .historyApiFallback(true)
      .headers({ "Access-Control-Allow-Origin": ["*"] });
  },
};

Thus, the submission of the form described in Part II occurs in the file gcode_frontend/src/components/Registration.vue

<template>
<v-layout justify-center>
  <v-form
    ref="form"
    lazy-validation
  >
  <v-row>
    <h1><p>Create Profile</p></h1>
    <v-col cols="10" lg="12">
        <v-text-field
          v-model="email"
          :error-messages="emailErrors"
          label="Email"
          required
          @input="$v.email.$touch()"
        ></v-text-field>
    </v-col>
  </v-row>

  <v-row>
    <v-col cols="10" lg="12">
        <v-text-field
          v-model="password"
          :error-messages="passwordErrors"
          label="Password"
          type="password"
          required
          @input="$v.password.$touch()"
        ></v-text-field>
    </v-col>
  </v-row>

  <v-row>
    <v-col cols="10" lg="12">
        <v-text-field
          v-model="repeatPassword"
          :error-messages="repeatPasswordErrors"
          label="Repeat Password"
          type="password"
          required
          @input="$v.repeatPassword.$touch()"
        ></v-text-field>
    </v-col>
  </v-row>

  <v-row>
    <v-col cols="10" lg="12">
        <v-text-field
          v-model="first_name"
          :error-messages="first_nameErrors"
          label="First Name"
          required
          @input="$v.first_name.$touch()"
        ></v-text-field>
    </v-col>
  </v-row>

  <v-row>
    <v-col cols="10" lg="12">
        <v-text-field
          v-model="last_name"
          :error-messages="last_nameErrors"
          label="Last Name"
          required
          @input="$v.last_name.$touch()"
        ></v-text-field>
    </v-col>
  </v-row>

  <v-row>
    <v-col cols="10" lg="12">
        <v-text-field
          v-model="phone"
          label="Phone"
          @input="$v.phone.$touch()"
        ></v-text-field>
    </v-col>
  </v-row>

    <v-btn
      color="success"
      class="mr-4"
      :disabled="submitStatus === 'PENDING'"
      @click="submit"
    >
      Create
    </v-btn>
    <p v-if="submitStatus === 'OK'"> Thanks for your submission! </p>
    <p v-if="submitStatus === 'ERROR'"> Please fill the form correctly. </p>
    <p v-if="submitStatus === 'PENDING'"> Sending... </p>
  </v-form>
</v-layout>
</template>

<script>
import axios from 'axios'
import { validationMixin } from 'vuelidate'
import { required, minLength, email, sameAs } from 'vuelidate/lib/validators'

export default {
    mixins: [validationMixin],

    validations: {
      email: { required, email },
      password: { required, minLength: minLength(6) },
      repeatPassword: { required, sameAsPassword: sameAs('password') },
      first_name: { required },
      last_name: { required }
    },

    data: function () {
      return {
        email: '',
        password: '',
        repeatPassword: '',
        first_name: '',
        last_name: '',
        phone: '',
        submitStatus: null
      }
    },

    computed: {
      emailErrors () {
        const errors = []
        if (!this.$v.email.$dirty) return errors
        !this.$v.email.required && errors.push('Email is required.')
        !this.$v.email.email && errors.push('Must be valid e-mail')
        return errors
      },
      passwordErrors () {
        const errors = []
        if (!this.$v.password.$dirty) return errors
        !this.$v.password.required && errors.push('Password is required')
        !this.$v.password.minLength && errors.push('Password must be at least 6 characters')
        return errors
      },
      repeatPasswordErrors () {
        const errors = []
        if (!this.$v.repeatPassword.$dirty) return errors
        !this.$v.repeatPassword.sameAsPassword && errors.push('Passwords must be identical')
        return errors
      },
      first_nameErrors () {
        const errors = []
        if (!this.$v.first_name.$dirty) return errors
        !this.$v.first_name.required && errors.push('First Name is required')
        return errors
      },
      last_nameErrors () {
        const errors = []
        if (!this.$v.last_name.$dirty) return errors
        !this.$v.last_name.required && errors.push('Last Name is required')
        return errors
      }
    },

    methods: {
        submit () {
          console.log('submit!')
          this.$v.$touch()
          if (this.$v.$invalid) {
            this.submitStatus = 'ERROR'
          } else {
            // do your submit logic here
            console.log('send...')
            this.Registration()
            this.submitStatus = 'PENDING'
            setTimeout(() => {
              this.submitStatus = 'OK'
            }, 500)
          }
        },

        Registration: function () {
          const formData = new FormData()
          if (this.email !== '') {
              formData.append('email', this.email)
          }
          if (this.password !== '') {
              formData.append('password', this.password)
          }
          if (this.repeatPassword !== '') {
              formData.append('repeatPassword', this.repeatPassword)
          }
          if (this.first_name !== '') {
              formData.append('first_name', this.first_name)
          }
          if (this.last_name !== '') {
              formData.append('last_name', this.last_name)
          }
          if (this.phone !== '') {
              formData.append('phone', this.phone)
          }
          console.log(formData)
          axios({
            method: 'post',
            url: 'http://127.0.0.1:8000/api/v1/registration',
            data: formData,
            headers: { 'Content-Type': 'multipart/form-data' }
            }).then(response => {
                    if (response.status === 200) {
                      console.log(response.data)
                    } else {
                      console.log(response.data)
                    }
               })
               .catch((error) => {
                    console.log(JSON.stringify(error.response.data))
                })
        }
    }
}
</script>

For form validation on the frontend, I use app vuelidate line 97, 98.

Line 103-109 ==> what types of validation we will use for each form field

Line 123-156 ==> error messages

As a result, the form will look like this:

Post your comment

Search
Popular Posts
Subscribe
{{post}}