Categories
Vue

Add a Modal to a Vue App with the vue-js-modal Library

The Vue.js modal library is a popular and useful modal library for Vue apps.

In this article, we’ll look at how to add a modal with the vue-js-modal library.

Installation

We can install the library by running:

npm i vue-js-modal

or

yarn add vue-js-modal

Add a Modal

Once we install the modal, then we can use it by writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import VModal from "vue-js-modal";
Vue.use(VModal);

Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

App.vue

<template>
  <modal name="hello-world-modal">hello world modal</modal>
</template>

<script>
export default {
  name: "App",
  methods: {
    show() {
      this.$modal.show("hello-world-modal");
    },
    hide() {
      this.$modal.hide("hello-world-modal");
    }
  },
  mounted() {
    this.show();
  }
};
</script>

We add the modal component with the name prop so that we can assign the name to it.

This way, we can show and hide the modal.

Also, we can create dynamic modals by call the this.$modal.show method with a component.

For example, we can write:

components/ModalContent.vue

<template>
  <div>{{text}}</div>
</template>

<script>
export default {
  name: "ModalContent",
  props: {
    text: String
  }
};
</script>

App.vue

<template>
  <div></div>
</template>

<script>
import ModalContent from "./components/ModalContent.vue";
export default {
  name: "App",
  methods: {
    show() {
      this.$modal.show(
        ModalContent,
        { text: "hello world" },
        { draggable: true }
      );
    }
  },
  mounted() {
    this.show();
  }
};
</script>

We call the show method with the component as the first argument.

The 2nd argument is an object with the props.

The last argument has the options for the modal.

The draggable property makes the modal draggable if it’s true .

We can also pass in a component that’s defined inline instead of importing it:

<template>
  <div></div>
</template>
<script>
export default {
  name: "App",
  methods: {
    show() {
      this.$modal.show(
        {
          template: `
            <div>
              <p>{{ text }}</p>
            </div>
          `,
          props: ["text"]
        },
        { text: "hello world" },
        { draggable: true },
        { "before-close": event => console.log("before close") }
      );
    }
  },
  mounted() {
    this.show();
  }
};
</script>

We added a 4th argument to listen to the before-close event emitted by the modal before it’s closed.

Also, we can set the options globally when we register the plugin.

For example, we can write:

main.js

import Vue from "vue";
import App from "./App.vue";
import VModal from "vue-js-modal";
Vue.use(VModal, {
  dynamicDefaults: {
    draggable: true,
    resizable: true,
    height: "auto"
  }
});

Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

App.vue

<template>
  <div></div>
</template>
<script>
export default {
  name: "App",
  methods: {
    show() {
      this.$modal.show(
        {
          template: `
            <div>
              <p>{{ text }}</p>
            </div>
          `,
          props: ["text"]
        },
        { text: "hello world" }
      );
    }
  },
  mounted() {
    this.show();
  }
};
</script>

We make all the modals added with the draggable and resizable properties added when we call Vue.use .

Conclusion

The vue-js-modal library lets us add modals easily into our Vue app.

Categories
Vue

Add a Circular Progress Display with vue2-circle-progress

The add a circular spinner easily into a Vue app, we can use the vue-circle-progress library.

In this article, we’ll look at how to use it to add the spinner.

Installation

We can install the package by running:

npm i vue2-circle-progress

Usage

After installing the package, we can use it by writing:

<template>
  <div id="app">
    <vue-circle
      :progress="50"
      :size="100"
      :reverse="false"
      line-cap="round"
      :fill="fill"
      empty-fill="rgba(0, 0, 0, .1)"
      :animation-start-value="0.0"
      :start-angle="0"
      insert-mode="append"
      :thickness="5"
      :show-percent="true"
      @vue-circle-progress="progress"
      @vue-circle-end="progressEnd"
    >
      <p>Slot!</p>
    </vue-circle>
  </div>
</template>

<script>
import VueCircle from "vue2-circle-progress";
export default {
  components: {
    VueCircle
  },
  data() {
    return {
      fill: { gradient: ["red", "green", "blue"] }
    };
  },
  methods: {
    progress(event, progress, stepValue) {
      console.log(stepValue);
    },
    progressEnd(event) {
      console.log("Circle progress end");
    }
  }
};
</script>

The progress prop sets the progress to display at the end.

size is the diameter of the circular progress display.

reverse makes animation run counterclockwise.

line-cap sets the line cap.

fill has the fill color.

fill can also be a single color, we can set replace the gradient property with the color property.

And it can also be replaced with the image property.

So we can write:

{ color: "green" }

or

{ image: "https://picsum.photos/id/23/200/300" }

to add an image.

empty-fill has the fill color for an empty bar.

animation-start-value has the starting progress value.

start-angle is the starting angle of the circular progress spinner.

insert-mode specifies how the spinner is appended to the DOM.

thickness is the thickness of the line in pixels.

It also emits several events. The vue-circle-progress event is emitted when the circular progress spinner is loading.

vue-circle-end is emitted when the circle finishes loading.

The progress method has the stepValue parameter to get the progress value that’s being displayed.

The default slot has the content inside the circle.

Methods

It also comes with a few methods.

The updateProgress method updates the component progress value and animate the changes.

For example, we can write:

<template>
  <div id="app">
    <vue-circle
      :progress="50"
      :size="100"
      :reverse="false"
      line-cap="round"
      :fill="fill"
      empty-fill="rgba(0, 0, 0, .1)"
      :animation-start-value="0.0"
      :start-angle="0"
      insert-mode="append"
      :thickness="5"
      :show-percent="true"
      @vue-circle-progress="progress"
      @vue-circle-end="progressEnd"
      ref="circleProgress"
    >
      <p>Slot!</p>
    </vue-circle>
    <button @click="updateProgress">update progress</button>
  </div>
</template>

<script>
import VueCircle from "vue2-circle-progress";
export default {
  components: {
    VueCircle
  },
  data() {
    return {
      fill: { gradient: ["red", "green", "blue"] }
    };
  },
  methods: {
    progress(event, progress, stepValue) {
      console.log(stepValue);
    },
    progressEnd(event) {
      console.log("Circle progress end");
    },
    updateProgress() {
      this.$refs.circleProgress.updateProgress(21);
    }
  }
};
</script>

to add an update progress button to change the progress percentage.

We call updateProgress by assigning the component a ref and call it from the ref.

Conclusion

We can add a circular progress display with the vue-circular-progress library.

Categories
Vue

Create a Simple Vue.js Registration Form

Registrations forms are a part of many web apps.

We can create one easily.

In this article, we’ll look at how to create a registration form with Vue and Express.

Back End

We can create a simple login form that takes some data in the back end.

To do that, we create an Express app by installing some packages:

npm i express cors body-parser

Then we can use them by writing:

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors')
const app = express();
app.use(cors())
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.post('/register', (req, res) => {
  res.json(req.body);
});

app.listen(3000, () => console.log('server started'));

The cors package lets us do cross-domain communication.

We used it with app.use(cors()) .

bodyParser parses the JSON request body that we’ll submit from the front end.

bodyParser.json() lets us parse JSON.

We also have a register route to get the request data.

req.body has the parsed JSON data.

If we need logic for checking for data, we can add them.

Register Form Front End

After we added the back end for accepting the registration data, we can add the registration form with Vue.js.

To do that, we can write:

<template>
  <div id="app">
    <form @submit.prevent="login">
      <div>
        <label for="username">username</label>
        <input name="username" v-model="username" placeholder="username">
      </div>
      <div>
        <label for="password">password</label>
        <input name="password" v-model="password" placeholder="password" type="password">
      </div>
      <div>
        <label for="firstName">first name</label>
        <input name="firstName" v-model="firstName" placeholder="first name">
      </div>
      <div>
        <label for="lastName">last name</label>
        <input name="lastName" v-model="lastName" placeholder="last name">
      </div>
      <div>
        <label for="age">age</label>
        <input name="age" v-model="age" placeholder="age" type="number">
      </div>
      <div>
        <label for="address">address</label>
        <input name="address" v-model="address" placeholder="address">
      </div>
      <input type="submit" value="register">
    </form>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      username: "",
      password: "",
      firstName: "",
      lastName: "",
      age: "",
      address: ""
    };
  },
  methods: {
    async login() {
      const { username, password, firstName, lastName, age, address } = this;
      const res = await fetch(
        "https://SomberHandsomePhysics--five-nine.repl.co/register",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json"
          },
          body: JSON.stringify({
            username,
            password,
            firstName,
            lastName,
            age,
            address
          })
        }
      );
      const data = await res.json();
      console.log(data);
    }
  }
};
</script>

We added a registration form with the form element.

The submit.prevent listen runs the login method on submit and runs preventDefault at the same time.

The form fields are created by the label and input tags.

for has the name attribute value of the input field.

v-model binds to the values that we submit.

We also set the type attribute of some inputs.

password is for password inputs.

number is for number inputs.

The login method calls fetch to make a POST request to the back end.

We get all the reactive properties we want to submit in the first line.

Then we put them all in the JSON string.

headers must have the Content-Type set to application/json to submit the JSON.

Then we get back the response from the register route once the request is made.

Conclusion

We can create a registration form with Vue.js with the v-model directive and the fetch function to make requests.

Categories
Vue

Create a Simple Vue.js Login Form — an Example

Login forms are a part of most web apps.

We can create one easily.

In this article, we’ll look at how to create a login form with Vue and Express.

Back End

We can create a simple login form that takes some data in the back end.

To do that, we create an Express app by installing some packages:

npm i express cors body-parser

Then we can use them by writing:

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors')
const app = express();
app.use(cors())
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.post('/login', (req, res) => {
  res.json(req.body);
});

app.listen(3000, () => console.log('server started'));

The cors package lets us do cross-domain communication.

We used it with app.use(cors()) .

bodyParser parses the JSON request body that we’ll submit from the front end.

bodyParser.json() lets us parse JSON.

We also have a login route to get the request data.

req.body has the parsed JSON data.

We should add logic for user validation when we create a production app.

Login Form Front End

We add the login form in our Vue app.

To do that, we can write:

<template>
  <div id="app">
    <form @submit.prevent="login">
      <input v-model="username" placeholder="username">
      <input v-model="password" placeholder="password" type="password">
      <input type="submit" value="log in">
    </form>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      username: "",
      password: ""
    };
  },
  methods: {
    async login() {
      const { username, password } = this;
      const res = await fetch(
        "https://SomberHandsomePhysics--five-nine.repl.co/login",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json"
          },
          body: JSON.stringify({ username, password })
        }
      );
      const data = await res.json();
      console.log(data);
    }
  }
};
</script>

We created the login form in the template.

v-model binds the data to the reactive properties we initialized in the data method.

The input with type submit will trigger the submit event.

We listen to the submit event with submit.prevent to call preventDefault automatically.

This way, we can submit our login credentials with JavaScript.

Then in the login method, we called fetch to make a request to the login route we created.

The method property has the request method.

headers has the request headers. We need to set Content-Type to application/json so that we can submit JSON.

The body has the requests body.

Then we get back the response with res.json() .

When we type in something and click ‘log in’, we should get a response logged.

Conclusion

We can create a simple login form with Vue and Express easily.

Categories
Vue

Create a Search Filter with Vue.js

We can create a search filter with Vue.js to let us add search functionality to our app.

In this article, we’ll look at how to add a search filter to our Vue app.

Computed Properties

We can create a computed property that watches reactive properties and return a value derived from them.

For instance, we can write:

<template>
  <div id="app">
    <p>original message: "{{ message }}"</p>
    <p>reversed message: "{{ reversedMessage }}"</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      message: "Hello"
    };
  },
  computed: {
    reversedMessage() {
      return this.message
        .split("")
        .reverse()
        .join("");
    }
  }
};
</script>

to create the reversedMessage computed property to reverse the this.message string and return it.

Then we can use it in the template like a regular reactive property.

A computed property function must be synchronous so that it returns a value.

Computed properties are useful because they don’t update until the reactive properties update.

Also, the returned value is cached when they don’t need to update unnecessarily.

This is very handy for creating search filters since the filter only updates when we update the search term.

Creating a Search Filter

We can create a search filter with it by using computed properties.

To do that, we write:

<template>
  <div id="app">
    <input v-model="searchQuery">
    <div v-for="r of resultQuery" :key="r.id">{{r.title}}</div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      searchQuery: null,
      resources: [
        { id: 1, title: "javascript for dummies" },
        { id: 2, title: "vue for dummies" },
        { id: 3, title: "dos for dummies" },
        { id: 4, title: "windows for dummies" },
        { id: 5, title: "html for dummies" }
      ]
    };
  },
  computed: {
    resultQuery() {
      if (this.searchQuery) {
        return this.resources.filter(item => {
          return this.searchQuery
            .toLowerCase()
            .split(" ")
            .every(v => item.title.toLowerCase().includes(v));
        });
      } else {
        return this.resources;
      }
    }
  }
};
</script>

We have the resources array that has all the array items we can search for.

Also, we have the resultQuery computed property to do the search.

We call filter on this.resources is this.searchQuery isn’t an empty string.

In the filter callback, we split the searchQuery string and check if the title has the parts of the searchQuery string.

Otherwise, we return the this.resources array.

In the template, we have the input box to let us search for the items.

It binds to this.searchQuery , so the resultQuery will be computed.

We loop through the resultQuery array and display so that we display the filtered results.

The key prop is required so that the items displayed properly.

Therefore, when we type something into the input box, we’ll see the filtered results updated automatically.

Conclusion

We can add our own search filter easily with Vue.js computed properties.