Categories
Vue 3

Add a Swiper Carousel into a Vue 3 App with Swiper 6

Swiper for Vue.js lets us add a carousel to our Vue 3 app.

In this article, we’ll look at how to add a carousel into our Vue 3 app with Swiper.

Virtual Slides

We can add virtual slides, which are slides that are rendered completely by Vue 3.

It doesn’t require anything except the virtual prop.

For instance, we can write:

<template>
  <swiper
    :slides-per-view="3"
    :space-between="50"
    @swiper="onSwiper"
    @slideChange="onSlideChange"
    virtual
  >
    <swiper-slide v-for="n of 50" :virtualIndex="n" :key="n"
      >Slide {{ n }}</swiper-slide
    >
  </swiper>
</template>
<script>
import SwiperCore, { Virtual } from "swiper";
import { Swiper, SwiperSlide } from "swiper/vue";
import "swiper/swiper-bundle.css";

SwiperCore.use([Virtual]);

export default {
  components: {
    Swiper,
    SwiperSlide,
  },
  methods: {
    onSwiper(swiper) {
      console.log(swiper);
    },
    onSlideChange() {
      console.log("slide change");
    },
  },
};
</script>

to add the swiper component that renders virtual slides.

Also, we have to add SwiperCore.use([Virtual]) to add the Virtual plugin so that we can render virtual slides.

Controller

We can add a slider that’s controlled by another slider.

For instance, we can write:

<template>
  <swiper
    :slides-per-view="3"
    :space-between="50"
    @swiper="setControlledSwiper"
  >
    <swiper-slide v-for="n of 50" :virtualIndex="n" :key="n"
      >Slide {{ n }}</swiper-slide
    >
  </swiper>

  <swiper :controller="{ control: controlledSwiper }">
    <swiper-slide v-for="n of 50" :virtualIndex="n" :key="n"
      >Slide {{ n }}</swiper-slide
    >
  </swiper>
</template>

<script>
import SwiperCore, { Controller } from "swiper";
import { Swiper, SwiperSlide } from "swiper/vue";
import "swiper/swiper-bundle.css";

SwiperCore.use([Controller]);

export default {
  components: {
    Swiper,
    SwiperSlide,
  },
  data() {
    return {
      controlledSwiper: null,
    };
  },
  methods: {
    setControlledSwiper(swiper) {
      this.controlledSwiper = swiper;
    },
  },
};
</script>

The first swiper controls the behavior of the 2nd swiper.

We do this by calling the setControlledSwiper method when the first swiper is initialized.

In the method, we just set swiper as the value of this.controlledSwiper .

Now in the 2nd swiper , we pass in an object with the control property set to controlledSwiper into the controller prop to let the first swiper control the 2nd one.

We also have to addSwiperCore.use([Controller]) to let us add controlled swipers.

Also, we can add 2-way control to swipers.

For instance, we can write:

<template>
  <swiper
    :slides-per-view="3"
    :space-between="50"
    @swiper="setFirstSwiper"
    :controller="{ control: secondSwiper }"
  >
    <swiper-slide v-for="n of 50" :virtualIndex="n" :key="n"
      >Slide {{ n }}</swiper-slide
    >
  </swiper>

  <swiper @swiper="setSecondSwiper" :controller="{ control: firstSwiper }">
    <swiper-slide v-for="n of 50" :virtualIndex="n" :key="n"
      >Slide {{ n }}</swiper-slide
    >
  </swiper>
</template>

<script>
import SwiperCore, { Controller } from "swiper";
import { Swiper, SwiperSlide } from "swiper/vue";
import "swiper/swiper-bundle.css";

SwiperCore.use([Controller]);

export default {
  components: {
    Swiper,
    SwiperSlide,
  },
  data() {
    return {
      firstSwiper: null,
      secondSwiper: null,
    };
  },
  methods: {
    setFirstSwiper(swiper) {
      this.firstSwiper = swiper;
    },
    setSecondSwiper(swiper) {
      this.secondSwiper = swiper;
    },
  },
};
</script>

We have the setFirstSwiper and setSecondSwiper to set the firstSwiper and secondSwiper reactive properties respectively.

Then we pass them as values of the controller prop to enable control of them.

Now when we swipe one of the sliders, the other one will change.

Conclusion

We can add more complex sliders into our Vue 3 app with Swiper 6.

Categories
React

Make Form Handling Easy in React Apps with Formik — Hooks

Formik is a library that makes form handling in React apps easy.

In this article, we’ll look at how to handle form inputs with Formik

useField

We can use the useField hook to create our own text fields that work with Formik.

For instance, we can write:

import React from "react";
import { useField, Form, Formik } from "formik";

const MyTextField = ({ label, ...props }) => {
  const [field, meta] = useField(props);
  return (
    <>
      <label>
        {label}
        <input {...field} {...props} />
      </label>
      {meta.touched && meta.error ? (
        <div className="error">{meta.error}</div>
      ) : null}
    </>
  );
};

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        email: ""
      }}
      onSubmit={(values, actions) => {
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          actions.setSubmitting(false);
        }, 1000);
      }}
    >
      {(props) => (
        <Form>
          <MyTextField name="email" type="email" label="Email" />
          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We create the MyTextField component with the useField hook.

And we pass in the props and the field objects into the input as props to let Formik bind to states and set input statuses like touched and error .

Then in FormExample , we create our form with the Formik and Form components as usual.

But we use the MyTextField component to add our input field into the form.

useFormik

We can use the useFormik hook to create Formik forms.

For instance, we can write:

import React from "react";
import { useFormik } from "formik";

export const FormExample = () => {
  const formik = useFormik({
    initialValues: {
      firstName: "",
      lastName: "",
      email: ""
    },
    onSubmit: (values) => {
      alert(JSON.stringify(values, null, 2));
    }
  });
  return (
    <form onSubmit={formik.handleSubmit}>
      <label htmlFor="firstName">First Name</label>
      <input
        id="firstName"
        name="firstName"
        type="text"
        onChange={formik.handleChange}
        value={formik.values.firstName}
      />
      <label htmlFor="lastName">Last Name</label>
      <input
        id="lastName"
        name="lastName"
        type="text"
        onChange={formik.handleChange}
        value={formik.values.lastName}
      />
      <label htmlFor="email">Email Address</label>
      <input
        id="email"
        name="email"
        type="email"
        onChange={formik.handleChange}
        value={formik.values.email}
      />
      <button type="submit">Submit</button>
    </form>
  );
};

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

We add the useFormik to FormExample to let us create a form with Formik.

We pass the initialValues inside to set the initial values.

onSubmit has the submit handler for the form.

Then we can get the properties from the formik object.

This includes the onSubmit callback, which is set to formik.handleSubmit .

formik.handleChange is the change handler for the form fields.

form.values has the form values.

useFormikContext

We can use the useFormikContext hook to let us access the form from components inside the form.

For instance, we can write:

import React from "react";
import { Field, Form, Formik, useFormikContext } from "formik";

const AutoSubmitToken = () => {
  const { values, submitForm } = useFormikContext();
  React.useEffect(() => {
    if (values.token.length === 6) {
      submitForm();
    }
  }, [values, submitForm]);
  return null;
};

export const FormExample = () => {
  return (
    <Formik
      initialValues={{ token: "" }}
      validate={(values) => {
        const errors = {};
        if (values.token.length < 5) {
          errors.token = "Invalid code. Too short.";
        }
        return errors;
      }}
      onSubmit={(values, actions) => {
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          actions.setSubmitting(false);
        }, 1000);
      }}
    >
      <Form>
        <Field name="token" type="tel" />
        <AutoSubmitToken />
      </Form>
    </Formik>
  );
};

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

We have the AutoSubmitToken component that has the values property with the form values.

submitForm has the form submit function.

useFormikContext returns an object with all those properties.

The FormExample has the usual props and components to create the form and the AutoSubmitToken component that submits the form automatically values.token.length is bigger than or equal to 6.

Conclusion

We can use the hooks that comes with Formik to create our forms.

Categories
React

Make Form Handling Easy in React Apps with Formik — Dependant Fields and Object Array Fields

Formik is a library that makes form handling in React apps easy.

In this article, we’ll look at how to handle form inputs with Formik

Dependent Fields

We can set one field’s value based on a value of another field.

For instance, we can write:

import React from "react";
import { Formik, Field, Form, useField, useFormikContext } from "formik";

const MyField = (props) => {
  const {
    values: { textA },
    touched,
    setFieldValue
  } = useFormikContext();
  const [field, meta] = useField(props);

  React.useEffect(() => {
    if (textA.trim() !== "" && touched.textA) {
      setFieldValue(props.name, `textA: ${textA}`);
    }
  }, [textA, touched.textA, setFieldValue, props.name]);

  return (
    <>
      <input {...props} {...field} />
      {!!meta.touched && !!meta.error && <div>{meta.error}</div>}
    </>
  );
};

const initialValues = { textA: "", textB: "" };

export const FormExample = () => (
  <div>
    <Formik
      initialValues={initialValues}
      onSubmit={async (values) => alert(JSON.stringify(values, null, 2))}
    >
      <Form>
        <label>
          textA
          <Field name="textA" />
        </label>
        <label>
          textB
          <MyField name="textB" />
        </label>
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We created the MyField component and use the useFormikContext component to get the status of the textA field.

We get its value from the values.textA property.

touched has the touched value.

setFieldValue lets us set the field value of another field.

We watch the value the textA field with the useEffect callback and the array with the textA field value, the touched.textA property which has the touched status of textA , setFieldValue , and props.name .

We watch all of them for changes.

Then in FormExample , we use MyField to create the textB field.

It watches the textA field for changes, so when we enter something into the textA field, we see the text of the textB set with the value of textA .

Object Array Fields

We can bind fields to an array of objects.

To do this, we write:

import React from "react";
import { Formik, Field, Form, FieldArray, ErrorMessage } from "formik";

const initialValues = {
  friends: [
    {
      name: "",
      email: ""
    }
  ]
};

export const FormExample = () => (
  <div>
    <Formik
      initialValues={initialValues}
      onSubmit={async (values) => {
        await new Promise((r) => setTimeout(r, 500));
        alert(JSON.stringify(values, null, 2));
      }}
    >
      {({ values }) => (
        <Form>
          <FieldArray name="friends">
            {({ remove, push }) => (
              <div>
                {values.friends.length > 0 &&
                  values.friends.map((friend, index) => (
                    <div className="row" key={index}>
                      <div className="col">
                        <label htmlFor={`friends.${index}.name`}>Name</label>
                        <Field name={`friends.${index}.name`} type="text" />
                        <ErrorMessage
                          name={`friends.${index}.name`}
                          component="div"
                          className="field-error"
                        />
                      </div>
                      <div className="col">
                        <label htmlFor={`friends.${index}.email`}>Email</label>
                        <Field name={`friends.${index}.email`} type="email" />
                        <ErrorMessage
                          name={`friends.${index}.name`}
                          component="div"
                          className="field-error"
                        />
                      </div>
                      <div className="col">
                        <button
                          type="button"
                          className="secondary"
                          onClick={() => remove(index)}
                        >
                          X
                        </button>
                      </div>
                    </div>
                  ))}
                <button
                  type="button"
                  className="secondary"
                  onClick={() => push({ name: "", email: "" })}
                >
                  Add
                </button>
              </div>
            )}
          </FieldArray>
          <button type="submit">Invite</button>
        </Form>
      )}
    </Formik>
  </div>
);

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

We just set the name to the path of the property we want to bind to in the Field component.

Likewise, we do the same with the ErrorMessage field to get the form validation error messages for the field with the given property path.

To remove an entry, we can use the remove function that comes with Formik.

Conclusion

We can add dependant fields and bind fields to an array of objects with Formik.

Categories
React

Make Form Handling Easy in React Apps with Formik — Checkboxes and Radio Buttons

Formik is a library that makes form handling in React apps easy.

In this article, we’ll look at how to handle form inputs with Formik.

Checkboxes

We can bind checkbox values to states with Formik.

For instance, we can write:

import React from "react";
import { Formik, Form, Field } from "formik";

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        toggle: false,
        checked: []
      }}
      onSubmit={(values) => {
        alert(JSON.stringify(values, null, 2));
      }}
    >
      {({ values }) => (
        <Form>
          <label>
            <Field type="checkbox" name="toggle" />
            {`${values.toggle}`}
          </label>
          <div>Checked</div>
          <div>
            <label>
              <Field type="checkbox" name="checked" value="apple" />
              apple
            </label>
            <label>
              <Field type="checkbox" name="checked" value="orange" />
              orange
            </label>
            <label>
              <Field type="checkbox" name="checked" value="grape" />
              grape
            </label>
          </div>

          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We set the initialValues to what we want.

In the first Field component, we set name to 'toggle' to bind to the toggle field.

This will bind the checked value to the values.toggle property.

It’ll be true when it’s checked and false otherwise.

In the div, we have 3 Field components.

We set the value in addition to the name to let us populate the checked array with the value prop value of the checkboxes that are checked.

When we submit the form, we see the checked items in checked and toggle is either true or false depending on whether it’s checked or not.

Radio Buttons

Formik also makes binding states to radio buttons easy.

To do this, we write:

import React from "react";
import { Formik, Form, Field } from "formik";

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        picked: ""
      }}
      onSubmit={(values) => {
        alert(JSON.stringify(values, null, 2));
      }}
    >
      {({ values }) => (
        <Form>
          <div>Picked</div>
          <div>
            <label>
              <Field type="radio" name="picked" value="apple" />
              One
            </label>
            <label>
              <Field type="radio" name="picked" value="orange" />
              Two
            </label>
            <div>Picked: {values.picked}</div>
          </div>

          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We set the name of the radio button groups to the same name.

And we also set the value for each.

Then we can pick one radio from the ones with the same name value.

And we’ll see the value with the value.picked property.

Conclusion

We can bind checkbox and radio button values to states with Formik.

Categories
React

Make Form Handling Easy in React Apps with Formik — Error Messages and Binding to Arrays and Nested Properties

Formik is a library that makes form handling in React apps easy.

In this article, we’ll look at how to handle form inputs with Formik.

Displaying Error Messages

We can display form validation error messages by rendering the values of the errors object.

For instance, we can write:

import React from "react";
import { Formik, Form, Field } from "formik";
import * as Yup from "yup";

const schema = Yup.object().shape({
  email: Yup.string().email("Invalid email").required("Required")
});

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        email: ""
      }}
      validationSchema={schema}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      {({ errors, touched }) => (
        <Form>
          <Field name="email" />
          {touched.email && errors.email && <div>{errors.email}</div>}
          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

Then we render the errors.email property to get the value of the email field.

When we type in something that’s not an email address, we’ll see the error message displayed.

Arrays and Nested Objects

Formik works with arrays and nested objects.

For example, we can bind form fields to nested properties by writing:

import React from "react";
import { Formik, Form, Field } from "formik";

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        social: {
          facebook: "",
          twitter: ""
        }
      }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      <Form>
        <Field name="social.facebook" />
        <Field name="social.twitter" />
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

In the initialValues prop, we have the social object with some properties inside.

To bind to those, we just set the name prop of the Field components to the property paths of those properties.

Then values in the onSubmit callback would have those values set.

We can also bind our Field input values to array entries.

To do this, we write:

import React from "react";
import { Formik, Form, Field } from "formik";

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        friends: ["james", "mary"]
      }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      <Form>
        <Field name="friends[0]" />
        <Field name="friends[1]" />
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We just set the name prop to the path to the array entry we want to bind to.

Also, we can remove nesting by adding properties with dots to separate the path segments.

For instance, we can write;

import React from "react";
import { Formik, Form, Field } from "formik";

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        "owner.name": ""
      }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      <Form>
        <Field name="['owner.name']" />
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We have the 'owner.name' property in initialValues .

Then we set the name prop to ['owner.name'] to do the binding automatically.

Conclusion

We can display form validation error messages and bind input fields to nested properties and array entries with Formik.