Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using setFieldValue for one field, based on another filed values

I'm using formik react library and trying to update 2 fields, based on the onChange event of another. For example,

price = quantity * totalPrice

price :
onChange={() => {setFieldValue('quantity',values.quantity? values.price / values.totalPrice:values.quantity, );
setFieldValue('totalPrice',values.totalPrice? values.price * values.quantity: values.totalPrice,);}}

quantity :
onChange={(value, e) => { this.disableFiled(value, e); setFieldValue('totalPrice',values.price ? values.price * values.totalPrice : ' ',);}}

totalPrice:
onChange={(value, e) => { this.disableFiled(value, e);setFieldValue('quantity',values.price ? values.totalPrice / price : ' ', ); }}

when quantity has value, total price will be disabled and vice versa.but it doesn't calculate other fields correctly

like image 729
Rahele Nazari Avatar asked Sep 24 '19 08:09

Rahele Nazari


People also ask

How do you set value in Formik field?

You don't need to use value={values.name} you can use Formik props like onSubmit to get your values. Also what version are you using? please note that render method has been deprecated.

How do you use set field value?

FieldByName(name = 'salary_fld'); ret_value = fld. SetFieldValue(value = 10000.0); The FieldByName method returns the field object that represents the given field (salary_fld, in this example), and the SetFieldValue methods uses that field object to set the value of the field.

What is dirty Formik?

Returns true if values are not deeply equal from initial values, false otherwise. dirty is a readonly computed property and should not be mutated directly.


Video Answer


1 Answers

This is how I do this.

App.js file:

import React from "react";
import "./styles.css";
import { Formik } from "formik";
import * as Yup from "yup";
import CalculatedField from "./CalculatedField";

const App = () => (
  <div className="app">
    <Formik
      initialValues={{ price: "", quantity: "", totalPrice: "" }}
      onSubmit={async values => {
        await new Promise(resolve => setTimeout(resolve, 500));
        alert(JSON.stringify(values, null, 2));
      }}
      validationSchema={Yup.object().shape({
        price: Yup.number("It's a number").required("Required"),
        quantity: Yup.number("It's a number").required("Required"),
        totalPrice: Yup.number("It's a number").required("Required")
      })}
    >
      {props => {
        const {
          values,
          touched,
          errors,
          isSubmitting,
          handleChange,
          handleBlur,
          handleSubmit,
          setFieldValue
        } = props;
        return (
          <form onSubmit={handleSubmit}>
            <div className="input-row">
              <label htmlFor="quantity" style={{ display: "block" }}>
                Quantity
              </label>
              <input
                id="quantity"
                name="quantity"
                placeholder="Enter quantity"
                type="number"
                value={values.quantity}
                onChange={handleChange}
                onBlur={handleBlur}
                className={
                  errors.quantity && touched.quantity
                    ? "text-input error"
                    : "text-input"
                }
              />
              {errors.quantity && touched.quantity && (
                <div className="input-feedback">{errors.quantity}</div>
              )}
            </div>
            <div className="input-row">
              <label htmlFor="price" style={{ display: "block" }}>
                Price
              </label>
              <input
                id="price"
                name="price"
                placeholder="Enter your price"
                type="number"
                value={values.price}
                onChange={handleChange}
                onBlur={handleBlur}
                className={
                  errors.price && touched.price
                    ? "text-input error"
                    : "text-input"
                }
              />
              {errors.price && touched.price && (
                <div className="input-feedback">{errors.price}</div>
              )}
            </div>

            <div className="input-row">
              <label htmlFor="totalPrice" style={{ display: "block" }}>
                Total Price
              </label>
              <CalculatedField
                id="totalPrice"
                type="number"
                name="totalPrice"
                value={values.totalPrice}
                values={values}
                setFieldValue={setFieldValue}
                onChange={handleChange}
                onBlur={handleBlur}
                className={
                  errors.totalPrice && touched.totalPrice
                    ? "text-input error"
                    : "text-input"
                }
              />
              {errors.totalPrice && touched.totalPrice && (
                <div className="input-feedback">{errors.totalPrice}</div>
              )}
            </div>

            <div className="input-row">
              <button type="submit" disabled={isSubmitting}>
                Submit
              </button>
            </div>
          </form>
        );
      }}
    </Formik>
  </div>
);
export default App;

CalculatedField.js

import React, { useEffect } from "react";

const CalculatedField = props => {
  useEffect(() => {
    var val = 0;
    if (props.values.price && props.values.quantity) {
      val = props.values.price * props.values.quantity;
    }
    props.setFieldValue("totalPrice", val);
  }, [props.values]);

  return (
    <input
      id="totalPrice"
      type="number"
      name="totalPrice"
      value={props.values.totalPrice}
    />
  );
};

export default CalculatedField;

This is basically achieved by calling setFieldValue method within useEffect hooks in the CalculatedField component. Please remember useEffect will watch for the change of the values and run the setFieldValue method when they are modified.

Please follow the CodeSandbox demo. https://codesandbox.io/s/affectionate-mirzakhani-who30?file=/src/App.js

like image 116
Choudhury Avatar answered Oct 12 '22 20:10

Choudhury