Categories
Vue

Vuelidate — Async Validation and Rules Data

Vue.js doesn’t come with any form validation capabilities by default.

Therefore, we need to add our own form validation library or with our own code.

In this article, we’ll look at how to validate forms with Vuelidate.

Asynchronous Validation

We can validate form fields asynchronously.

For example, we can write:

<template>
  <div id="app">
    <div :class="{ 'form-group--error': $v.$error }">
      <label>Name</label>
      <input v-model.trim="$v.name.$model">
    </div>
    <div v-if="!$v.name.required">Name is required.</div>
    <div v-if="!$v.name.isUnique">Name already exists.</div>
  </div>
</template>
<script>
import { required } from "vuelidate/lib/validators";

export default {
  name: "App",
  data() {
    return {
      name: ""
    };
  },
  validations: {
    name: {
      required,
      isUnique(value) {
        if (value === "") return true;
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve(typeof value === "string" && value.length % 2 !== 0);
          }, 350 + Math.random() * 300);
        });
      }
    }
  }
};
</script>

We have the isUnique method that returns a promise that resolves to true if value is string and its length is even.

value is the value that we inputted.

true means the value is invalid.

In the template, we just check the rule with the $v.name.isUnique property.

We can also use the async and await syntax for async validation.

We just return the resolved value inside the function:

validations: {
  async isUnique (value) {
    if (value === '') return true
    const response = await fetch(`/api/unique/${value}`)
    return Boolean(await response.json())
  }
}

Delayed Validation Errors

We can delay validation errors.

To do that, we can create a touch method that is delayed.

For example, we can write:

<template>
  <div id="app">
    <div :class="{ 'form-group--error': $v.$error }">
      <label>Name</label>
      <input v-model.trim="$v.name.$model" @input="delayTouch($v.name)">
    </div>
    <div v-if="!$v.name.required">Name is required.</div>
    <div
      class="error"
      v-if="!$v.name.minLength"
    >Name must have at least {{$v.name.$params.minLength.min}} letters.</div>
    <div
      class="error"
      v-if="!$v.name.maxLength"
    >Name must have at most {{$v.name.$params.maxLength.max}} letters.</div>
  </div>
</template>
<script>
import { required, minLength, maxLength } from "vuelidate/lib/validators";
const touchMap = new WeakMap();

export default {
  name: "App",
  data() {
    return {
      name: ""
    };
  },
  validations: {
    name: {
      required,
      minLength: minLength(4),
      maxLength: maxLength(15)
    }
  },
  methods: {
    delayTouch($v) {
      $v.$reset();
      if (touchMap.has($v)) {
        clearTimeout(touchMap.get($v));
      }
      touchMap.set($v, setTimeout($v.$touch, 1000));
    }
  }
};
</script>

to add a delayTouch method to run the form validation code with a delay.

We have a weak map to check store the timer that runs $v.$touch with a delay.

If the timer exists in the weak map, we clear the timeout.

This way, we won’t have to create a new timer every time delayTouch is run.

delayTouch is run when the input event is emitted.

Accessing Validator Parameters

We can access the $params property of the child field.

For example, we can write:

<template>
  <div id="app">
    <div :class="{ 'form-group--error': $v.$error }">
      <label>Name</label>
      <input v-model.trim="$v.form.name.$model">
    </div>
    <div v-if="!$v.form.name.required">Name is required.</div>
    <div
      v-if="!$v.form.name.minLength"
    >Name must have at least {{$v.form.name.$params.minLength.min}} letters.</div>
    <div
      v-if="!$v.form.name.maxLength"
    >Name must have at most {{$v.form.name.$params.maxLength.max}} letters.</div>
  </div>
</template>
<script>
import { required, minLength, maxLength } from "vuelidate/lib/validators";

export default {
  name: "App",
  data() {
    return {
      form: {
        name: ""
      }
    };
  },
  validations: {
    form: {
      name: {
        required,
        minLength: minLength(4),
        maxLength: maxLength(15)
      }
    }
  }
};
</script>

We have the $v.form.name.$params.minLength.min and $v.form.name.$params.maxLength.max properties to access the min and max number of allowed characters for the name field.

Conclusion

We can validate form fields asynchronously and access form validation rules data with Vuelidate.

Categories
React Vue

React vs Vue — Components and Props Basics

React is the most popular front end library for the last few years.

Vue is a front end framework that’s catching up in popularity with React in the last few years.

It’s hard to choose between the 2 frameworks since they both their pros and cons. When we choose one, we’ve to stick with it for a few years.

In this article, we’ll compare how we can create React and Vue components, handle props and which one is more convenient for developers.

Creating Components

With React, we create components by creating a function, with the props passed in the props parameter.

For example, we can create a component and pass a prop into it by writing the following code:

import React from "react";

function Foo({ msg }) {
  return <div>{msg}</div>;
}

export default function App() {
  return (
    <div className="App">
      <Foo msg="hello" />
    </div>
  );
}

In the code above, we created a Foo component with a msg prop that’s passed from App to Foo . Then we accessed the msg property of the prop parameter in the Foo component and displayed msg there.

With Vue, the way we define components and use them is similar to the React example.

We can create a Vue component and pass a prop into it as follows:

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <Foo msg="hello"></Foo>
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js :

Vue.component("Foo", {
  props: ["msg"],
  template: "<div>{{msg}}</div>"
});

const app = new Vue({
  el: "#app",
  data: {}
});

In the code above, we created a Foo component with Vue.component , and then designate the msg attribute as a prop.

Then in index.html , we reference Foo and pass in the msg prop as we did with the React example.

As we can see, this simple example is pretty comparable between React and Vue.

Passing Data From Child to Parent

React and Vue both have the capability to pass data from child to parent.

With React, we can pass a function to a child component that takes some arguments.

The child calls the function so that the parent can get the data.

We can do what we described with React as follows:

import React, { useState } from "react";

function FooInput({ setMsg }) {
  return <input onChange={e => setMsg(e.target.value)} />;
}

export default function App() {
  const [msg, setMsg] = useState();
  return (
    <div className="App">
      <FooInput setMsg={setMsg} />
      <br />
      <span>{msg}</span>
    </div>
  );
}

In the code above, we passed in the setMsg function returned from the useState hook to our FooInput component.

Then FooInput calls the setMsg function which we passed in from the props with the value of the input.

This will then set the inputted value as the value of msg .

Finally, we display the value of msg in the span.

With Vue, we don’t have to pass in the parent’s functions directly into the child component.

Instead, we can emit an event with the value that we want to send to the parent. Then the parent can do whatever they want with the value.

We can do the same thing in our React example with Vue as follows:

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <foo-input v-bind:value="msg" v-on:input="msg = $event"></foo-input>
      <br />
      <span>{{msg}}</span>
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js :

Vue.component("foo-input", {
  props: ["value"],
  data() {
    return {
      msg: ""
    };
  },
  watch: {
    value(val) {
      this.msg = val;
    }
  },
  template: `<input v-model="msg" @input="$emit('input', $event.target.value)">`
});

const app = new Vue({
  el: "#app",
  data: {
    msg: ""
  }
});

In the code above, we have the foo-input conponent, which takes a value prop, which we set the latest value to this.msg with the watcher so we aren’t mutating the value prop directly.

Then we call $emit with the input event name and the entered value, which is stored in $event.target.value .

The value entered is then sent to the parent and is available in the $event object.

We listen to the event set the value to the msg field by writing:

v-on:input="msg = $event"

as a directive on the foo-input component.

We then display the value of msg in the span below the foo-input component.

Once we did all that, we should see what we typed in displayed below the input.

A shorthand for:

v-bind:value="msg" v-on:input="msg = $event"

is:

v-model='msg'

This is a special case and doesn’t apply to app emitted events.

So we can instead write:

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <foo-input v-model="msg"></foo-input>
      <br />
      <span>{{msg}}</span>
    </div>
    <script src="index.js"></script>
  </body>
</html>

In any case, the React example is simpler. Passing data from child and parent components is definitely easier to React than Vue.

Verdict

The process for creating components and passing props from parent and child are pretty much the same when comparing React and Vue.

React does make passing data from child to parent easier than with Vue. We just pass in a function into the child and call it from there instead of emitting events and listening to them.

Categories
React Vue

React vs Vue — Event Handling

React is the most popular front end library for the last few years.

Vue is a front end framework that’s catching up in popularity with React in the last few years.

It’s hard to choose between the 2 frameworks since they both their pros and cons. When we choose one, we’ve to stick with it for a few years.

In this article, we’ll look at how we write event handling code with React and Vue and which one is more convenient.

Basic Event Handling

With React, we bind our event handlers straight into the JSX components.

For example, we can write the following code to do handle clicks with React:

import React, { useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);
  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div className="App">
      <button onClick={increment}>Increment</button>
      <div>{count}</div>
    </div>
  );
}

In the code above, we added the increment click handler and we pass that into the onClick prop so that when we click the Increment button, we’ll see the count value increase.

With Vue, we can write the following to do the same thing:

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="increment">Increment</button>
      <div>{{count}}</div>
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js :

const app = new Vue({
  el: "#app",
  data: {
    count: 0
  },
  methods: {
    increment() {
      this.count++;
    }
  }
});

In the code above, we have the increment handler as we did with the React example.

However, updating values is easier since we update the count directly instead of calling a function returned from the useState hook to update the count.

Passing in the click handler is pretty much done the same way, except that we have to remember to use the @click directive.

Handling clicks is pretty much the same in either case.

Modifying Event Handling Behavior

Vue has event modifiers to modify the behavior of how event handlers handle events.

We can put them after the event handling directive. For example, if we want to prevent the default submit behavior in a form, we write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <form v-on:submit.prevent="onSubmit">
        <input v-model="name" />
      </form>
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js :

const app = new Vue({
  el: "#app",
  data: {
    name: ""
  },
  methods: {
    onSubmit() {
      alert(this.name);
    }
  }
});

to add a form with a submit handler that doesn’t do the default submit behavior.

The .prevent modifier is a handy shortcut for calling e.preventDefault in our submit handler.

With React, we have to call preventDefault() .

The equivalent example in React would be:

import React, { useState } from "react";

export default function App() {
  const [name, setName] = useState("");
  const onSubmit = e => {
    e.preventDefault();
    alert(name);
  };

  return (
    <div className="App">
      <form onSubmit={onSubmit}>
        <input onChange={e => setName(e.target.value)} />
      </form>
    </div>
  );
}

The Vue version is slightly shorter, but it’s not too much different.

Photo by Jens Johnsson on Unsplash

Handling Key Presses

With Vue, we can handle keypresses with our event handlers with the v-on directive’s modifiers as we did with clicks.

For example, if we want to display an alert when we control-click on a div, we can write:

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <div v-on:click.ctrl="help">Help</div>
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js :

const app = new Vue({
  el: "#app",
  data: {},
  methods: {
    help() {
      alert("help");
    }
  }
});

In the code above, we have:

v-on:click.ctrl="help"

to run the help method when we control-click on the div.

With React, we have to use plain JavaScript to do this:

import React from "react";

export default function App() {
  const onClick = e => {
    e.stopPropagation();
    if (e.ctrlKey) {
      alert("help");
    }
  };

  return (
    <div className="App">
      <div onClick={onClick}>Help</div>
    </div>
  );
}

In the code above, we have an onClick handler that first stops the propagation of the events to its parent.

Then we check if the ctrlKey is pressed with the click.

Then we display the alert if e.ctrlKey is true , which means the control key is pressed.

This is definitely more complex with React. If we want to handle even more complex keyboard and mouse press combinations, this gets even harder.

Verdict

Event handling is better with Vue since it has modifiers to modify the behavior of event handling directives.

This is especially true when we need to handle more complex interactions like keyboard and mouse combinations.

There’s no easy way to do that with React.

Categories
React Vue

React vs Vue — Watching for Data

React is the most popular front end library for the last few years.

Vue is a front end framework that’s catching up in popularity with React in the last few years.

It’s hard to choose between the 2 frameworks since they both their pros and cons. When we choose one, we’ve to stick with it for a few years.

In this article, we’ll look at how we handle data with React and Vue and which one does a better job.

Computed Properties

Computed properties are data that are derived from another piece of data.

Vue has computed properties, which we can derive from existing data.

For example, we add the computed property to a Vue component as follows to add a computed property:

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="randomMsg">Random Msg</button>
      <div>{{msg}}</div>
      <div>{{reverseMsg}}</div>
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js :

const app = new Vue({
  el: "#app",
  data: {
    msg: "Hello world"
  },
  computed: {
    reverseMsg() {
      return this.msg
        .split("")
        .reverse()
        .join("");
    }
  },
  methods: {
    randomMsg() {
      const msgs = ["Hello world", "Hello Jane"];
      this.msg = msgs[Math.floor(Math.random() * msgs.length)];
    }
  }
});

In the code above, we have the randomMsg method which sets the message randomly.

The reverseMsg property will then be automatically computed according to what we return.

By default, computed properties are getter only, so it’s impossible for us to accidentally change a Vue computed property.

Then we can display them both on our template as we did above.

This is efficient for both developers and on computing resources since computed properties are only updated when the original data changed and developers only have to define one piece of code and use it everywhere.

With React, there’s no direct way to do the same thing. We have to use the useEffect hook to do the same thing by watching the original value that we want to create the computed property from.

Then we call the function returned from useState to make the change.

We do this as follows:

import React, { useState, useEffect } from "react";

export default function App() {
  const [msg, setMsg] = useState("Hello world");
  const [reverseMsg, setReverseMsg] = useState("");

  const randomMsg = () => {
    const msgs = ["Hello world", "Hello Jane"];
    setMsg(msgs[Math.floor(Math.random() * msgs.length)]);
  };

  useEffect(() => {
    setReverseMsg(
      msg
        .split("")
        .reverse()
        .join("")
    );
  }, [msg]);

  return (
    <div className="App">
      <button onClick={randomMsg}>Random Msg</button>
      <div>{msg}</div>
      <div>{reverseMsg}</div>
    </div>
  );
}

As we can see, this is more complex than the computed property solution that’s provided with Vue.

We have to watch the value of msg explicitly with the useEffect hook and then call setReverseMsg to set the value of it by reversing the string as we did with the Vue example.

The array [msg] tells React to watch for changes in value for msg .

We also have the randonMsg function to set the value of msg as we did with the Vue example.

Vue’s logic is definitely cleaner with computed properties. Also, we can do anything inside the useEffect hook callback, so we have to be careful not to accidentally change data that we don’t want to change.

Photo by John Torcasio on Unsplash

Watched Property

We can also watch for property changes with Vue. With React, we use the useEffect above as we did above to do that.

The equivalent of that with Vue os the watch property. We can use that as follows:

const app = new Vue({
  el: "#app",
  data: {
    msg: "Hello world",
    reverseMsg: ""
  },
  watch: {
    msg(val) {
      this.reverseMsg = val
        .split("")
        .reverse()
        .join("");
    }
  },
  methods: {
    randomMsg() {
      const msgs = ["Hello world", "Hello Jane"];
      this.msg = msgs[Math.floor(Math.random() * msgs.length)];
    }
  }
});

The code above watches for changes in the msg field. Then we can react to it by taking the val parameter, which has the current value of msg .

Then we reverse the string as we did before.

Vue is more flexible in that it provides both options.

Verdict

Computed properties is definitely a great feature that comes with Vue. This isn’t available to React.

The closest equivalent to Vue computed properties with React is the useEffect hook, where we can do anything.

Vue computed properties are getter-only by default so we can’t accidentally change computed properties unless we add a setter to it.

If we want to be more flexible, Vue also has watchers that do something equivalent to useEffect callbacks.

Therefore, Vue wins when it comes to creating derived properties.

Categories
React Vue

React vs Vue — App Creation and Display

React is the most popular front end library for the last few years.

Vue is a front end framework that’s catching up in popularity with React in the last few years.

It’s hard to choose between the 2 frameworks since they both their pros and cons. When we choose one, we’ve to stick with it for a few years.

In this article, we’ll look compare the most basic features of these 2 frameworks, which are creating the app and displaying data.

Creating the App

React has the Create React App command-line program which lets us create a scaffold of the app with JavaScript or TypeScript.

It has built-in support for building a progressive web app.

Create React App can run tests that are in the __tests__ folder.

Vue has the Vue CLI to create an app with a JavaScript or TypeScript, plus we can incorporate CSS, SASS, Less, etc. for styling. We can also add testing infrastructure right into our scaffold by changing the options that are shown in the Vue CLI.

We can also add Vue Router and Vuex from Vue CLI.

It also has support for building a progressive web app.

Vue CLI has a GUI for creating quick projects to prototype apps.

In addition to using CLI programs, we can use the script tag to add React and Vue to our app.

However, most React libraries are only available as NPM packages. Whereas many Vue libraries can be added via a script tag.

This means that Vue is more suitable for enhancing legacy apps since they often don’t have front ends that are built with modern frameworks and build tools.

It also makes Vue a better choice for quick prototyping since we can just add libraries via script tags and use them without thinking about build tools and scaffolding.

Template Syntax

Most React apps use JSX to display data on the screen. It’s a shortcut for calling the React.createElement method.

Vue templates have their own syntax. For example, we use double curly braces to display variables on the screen.

For example, we can write the following to display a variable’s value in a React app:

import React, { useState } from "react";

export default function App() {
  const [foo] = useState("foo");
  return <div className="App">{foo}</div>;
}

Whereas we write the following to display a variable’s value in a Vue app:

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      {{foo}}
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js :

const app = new Vue({
  el: "#app",
  data: {
    foo: "foo"
  }
});

In the code above, we display the value of the foo property in data in the template by writing:

{{foo}}

The React way is slightly simpler in that we put everything in the same component function.

On the other hand, we added what we want to display with Vue in a separate template.

In both cases, we have some new syntax to learn.

Conditionally Display Data

In React apps, we display items conditionally with normal if or switch statements in the render method of class components or returning JSX in function components.

The logic to toggle them on and off is all in the component file itself.

For example, we can write the following to toggle something on and off in a React app:

import React, { useState } from "react";

export default function App() {
  const [show, setShow] = useState();
  const toggleShow = () => {
    setShow(!show);
  };

  return (
    <div className="App">
      <button onClick={toggleShow}>Toggle</button>
      {show && <div>foo</div>}
    </div>
  );
}

In the code above, we added a Toggle button, and then the show state with the setShow function toggle the show state between true and false .

Then we show the div conditionally with:

{show && <div>foo</div>}

With Vue, we display items on the template and use v-if to control it.

For example, we can write the following code to do that:

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="toggle">Toggle</button>
      <div v-if="show">foo</div>
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js :

const app = new Vue({
  el: "#app",
  data: {
    show: false
  },
  methods: {
    toggle() {
      this.show = !this.show;
    }
  }
});

In the code above, we made the toggle method to toggle this.show on and off.

Then we added a Toggle button to call toggle and display it conditionally with the v-if directive.

As we can see, the React implementation is simpler than the Vue implementation.

We also have to understand the parts of a Vue component like when are components methods calls and where are states stored.

With the useState React hook, this is more obvious. We also don’t have to add things to templates and components to add something.

We can add everything to one file with React components. This is more convenient for simple components.

However, Vue’s approach is more convenient for separating logic from the display code.

This is a cleaner approach for organizing a component when things are more complex.

Verdict

Vue is more of a full-fledged framework, as opposed to React, which is more of a library.

The Vue CLI has many more options for creating an app with the options required for creating an app.

Create React App only has options for creating a basic app that doesn’t have routing or any state management solution.

This isn’t ideal since most people want a single-page app rather than enhancing a legacy app.

Also, Vue libraries are available as script tags, whereas most React libraries are only available as Node packages.

Vue is the clear winner with the Vue CLI with its options.

Displaying data are similar to both React and Vue. They both require some logic and display items and conditionally display items on the screen.

They both have their own workflows, but Vue’s design has cleaner separation between logic and templates, whereas React puts everything in one place.