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.

Installation

We can install the Swiper package by running:

npm i swiper

Basic Usage

Once we installed the package, we can add a slider by writing:

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

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

We add the swiper component to add the slider.

slides-per-view lets us set the number of slides to show per view.

space-between has the space between slides in pixels.

It emits the swiper event which is emitted when the slider is created.

slideChange event is emitted when we change slides.

We import the swiper/swiper-bundle.css file to add styles for the slides.

swiper-slide has the slides for the slider.

We can add the zoom prop to enable additional wrapper for zoom mode if it’s set to true .

virtualIndex has the index for virtual slides.

SwiperSlide Slot Props

We can get some data from the swiper-slide ‘s component’s slot props.

For example, we get the isActive prop to see if the slide is active:

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

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

It also provides the isPrev slot prop to see whether a slide is a slide previous to the active one.

The isNext slot prop to see whether a slide is a slide next to the active one.

isVisible indicates whether the current slide is visible.

isDuplicate indicates whether the slide is a duplicate slide.

Slots

We can populate slots provided by the swiper component.

For instance, we can write:

<template>
  <swiper
    :slides-per-view="3"
    :space-between="50"
    @swiper="onSwiper"
    @slideChange="onSlideChange"
  >
    <swiper-slide v-for="n of 50" :key="n">Slide {{ n }}</swiper-slide>
    <template v-slot:container-start>
      <span>Container Start</span>
    </template>
    <template v-slot:container-end>
      <span>Container End</span>
    </template>
    <template v-slot:wrapper-start>
      <span>Wrapper Start</span>
    </template>
    <template v-slot:wrapper-end>
      <span>Wrapper End</span>
    </template>
  </swiper>
</template>
<script>
import { Swiper, SwiperSlide } from "swiper/vue";
import "swiper/swiper-bundle.css";

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

We populate the container-start slot to add content to the top of the slider container.

container-end adds content to the bottom of the slider container

wrapper-start adds content before the first slide.

wrapper-end adds content after the last slide.

Conclsion

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

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.