Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
303 views
in Technique[技术] by (71.8m points)

javascript - enable the go to next step button, tried setting up state and created new onclick method in the radio button

update 2:

hi,

  • sorry I forgot to mention about the api call in my question earlier
  • I making an api call in redux way.
  • so in my actions/index.js file I am calling my api in getSports method.
  • but the problem is when I try to retrieve the values I am getting an error. A cross-origin error was thrown. React doesn't have access to the actual error object in development. See b.me/react-crossorigin-error for more information.
  • so I debugged the props in the class AsyncValidationForm console.log("AsyncValidationForm this.props---->", this.props);
  • there I dont see the getSports method.
  • can You tell me how to retrieve the values so that I can assign the them to my radio button label.

https://codesandbox.io/s/yv1zpj874x

actions/index.js

import axios from "axios";

export function testData() {
  let response = { data: "test" };
  return {

  };
}

export function getSports() {
  return dispatch => {
    axios
      .get("https://jsonplaceholder.typicode.com/users") //works
      .then(response => {

      })
      .catch(error => {

      });
  };
}

AsyncValidationForm.js

import * as actions from "../actions";


class AsyncValidationForm extends React.Component {
  constructor(props) {
    super(props);
    console.log("AsyncValidationForm  this.props---->", this.props);

    this.state = {
      //pass down VerticalLinearStepper.js state if any
      username: this.props.username ? this.props.username : "",
      password: this.props.password ? this.props.password : "",
      //this determines whether any fields is filled or not from VerticalLinearStepper
      pristine:
        this.props.username || this.props.password || !this.props.disabledNext
          ? false
          : true
    };
  }

radio button label in AsyncValidationForm.js

  <label>
          <Field
            name="sex"
            component={renderField}
            type="radio"
            value="male"
            checked={!this.props.disabledNext}
            onChange={this.passRadioValue}
          />{" "}
          Male
        </label>
  • I am new to redux form.
  • I am trying to enable the button after I click the radio button.
  • to enable the go to next step button I tried setting up state and created new onclick method in the radio button.
  • but still its throwing an error,
  • not sure how to pass the radio button values to enable the button.
  • Can you tell me how to fix it, so that in future I will fix it myself.
  • Providing my sandbox and relevant code snippet below.

update1: now only this error has been removed https://codesandbox.io/s/4jpkk394x7?moduleview=1

https://codesandbox.io/s/pjj6m1l9pq

AsyncValidationForm.js

const AsyncValidationForm = props => {
  console.log("AsyncValidationForm ---->");
  const { handleSubmit, pristine, reset, submitting } = props;
  // this.state = {

  //   disabled: false
  // };
  // this.setState({ disabled: !this.state.disabled });
  const passRadioValue = (e) =>{
  }
  return (
    <form onSubmit={handleSubmit}>
      <Field
        name="username"
        type="text"
        component={renderField}
        label="Username"
      />
      <Field
        name="password"
        type="password"
        component={renderField}
        label="Password"
      />
      <label>
        <Field name="sex" 
        component={renderField} type="radio" value="male"
          onClick={this.passRadioValue("right")} />{" "}
        Male
      </label>
      <div>
        <button type="submit" disabled={submitting}>
          Sign Up
        </button>
        <button type="button" disabled={pristine || submitting} onClick={reset}>
          Clear Values
        </button>
      </div>
    </form>
  );
};

StepTemplate.js

<Button
          variant="contained"
          color="primary"
          onClick={onNext}
          className={classes.button}
        >
          {canGoBack ? "Next" : "go to next step"}
        </Button>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

https://codesandbox.io/s/6zrw7r66rr

I have forked your codesandbox, and edit 4 files. Pretty sure it satisfies all your requirements stated above

VerticalLinearStepper.js: this is where we store our username, password, disabledNext (radioButton) state and handleChange method for setState. Then, we passed down the state to -> Step1.js -> AsyncValidationForm.js.

class VerticalLinearStepper extends React.Component {
  state = {
    activeStep: 0,
    //we set our state in this parent
    disabledNext: true,
    username: "",
    password: ""
  };

  steps = {
    "Select campaign settings": Step1,
    "Create an ad group": Step2,
    "Create an ad": Step3
  };

  //setState for disabledNext
  handleChangeDisabledNext = value => {
    this.setState({ disabledNext: value });
  };
  //setState for username, password
  handleChange = (name, value) => {
    this.setState({ [name]: value });
  };

  stepsCount = () => Object.values(this.steps).length;

  canGoBack = () => this.state.activeStep > 0;
  canGoForward = () => this.state.activeStep < this.stepsCount();

  isFinished = () => this.state.activeStep === this.stepsCount();

  handleBack = () => {
    if (this.canGoBack()) {
      this.setState(prevState => ({ activeStep: prevState.activeStep - 1 }));
    }
  };

  handleNext = () => {
    if (this.canGoForward()) {
      this.setState(prevState => ({ activeStep: prevState.activeStep + 1 }));
    }
  };

  handleReset = () => this.setState({ activeStep: 0 });

  render() {
    const { classes } = this.props;
    const { activeStep } = this.state;

    return (
      <div className={classes.root}>
        <Stepper activeStep={activeStep} orientation="vertical">
          {Object.entries(this.steps).map(([label, CustomStep]) => (
            <Step key={label}>
              <StepLabel>{label}</StepLabel>
              <StepContent>
                <CustomStep
                  canGoBack={this.canGoBack()}
                  canGoForward={this.canGoForward()}
                  onBack={this.handleBack}
                  onNext={this.handleNext}
                  classes={classes}
                  //we pass down the state and its' setState method
                  handleChangeDisabledNext={this.handleChangeDisabledNext}
                  disabledNext={this.state.disabledNext}
                  handleChange={this.handleChange}
                  username={this.state.username}
                  password={this.state.password}
                />
              </StepContent>
            </Step>
          ))}
        </Stepper>

        {this.isFinished() && (
          <Paper square elevation={0} className={classes.resetContainer}>
            <Typography>All steps completed - you&apos;re finished</Typography>
            <Button onClick={this.handleReset} className={classes.button}>
              Reset
            </Button>
          </Paper>
        )}
      </div>
    );
  }
}

In AsyncValidationForm.js, we bind onChange method to track the value and call the setState method and this.props.handleChange for setState in VerticalLinearStepper.js

const renderField = ({
  input,
  label,
  type,
  //checked is for radio, initialValue is for setting the username, password value
  checked,
  initialValue,
  meta: { asyncValidating, touched, error }
}) => {
  return (
    <div>
      <label>{label}</label>
      <div className={asyncValidating ? "async-validating" : ""}>
        <input
          {...input}
          value={initialValue} //add value attr
          checked={checked} //add checked attr
          type={type}
          placeholder={label}
        />
        {touched && error && <span>{error}</span>}
      </div>
    </div>
  );
};

class AsyncValidationForm extends React.Component {
  constructor(props) {
    super(props);
    console.log("AsyncValidationForm ---->");

    this.state = {
      //pass down VerticalLinearStepper.js state if any
      username: this.props.username ? this.props.username : "",
      password: this.props.password ? this.props.password : "",
      //this determines whether any fields is filled or not from VerticalLinearStepper
      pristine:
        this.props.username || this.props.password || !this.props.disabledNext
          ? false
          : true
    };
  }

  passRadioValue = e => {
    this.setState({ pristine: false }, () => {
      this.props.handleChangeDisabledNext(!e.target.checked);
    });
  };

  handleChange = name => event => {
    const value = event.target.value;
    this.setState(
      {
        [name]: value,
        pristine: false
      },
      () => {
        this.props.handleChange(name, value); //setState username, password of VerticalLinearStepper.js
      }
    );
  };

  resetForm = () => {
    this.props.handleChangeDisabledNext(true); //setState disabledNext of VerticalLinearStepper.js
    this.setState(
      {
        username: "",
        password: "",
        pristine: true
      },
      () => {
        this.props.handleChange("username", "");
        this.props.handleChange("password", "");
      }
    );

    this.props.reset();
  };

  // this.setState({ disabled: !this.state.disabled });

  render() {
    const { handleSubmit, pristine, reset, submitting } = this.props;

    return (
      <form onSubmit={handleSubmit}>
        <Field
          name="username"
          type="text"
          component={renderField}
          label="Username"
          initialValue={this.state.username}
          onChange={this.handleChange("username")}
        />
        <Field
          name="password"
          type="password"
          component={renderField}
          label="Password"
          initialValue={this.state.password}
          onChange={this.handleChange("password")}
        />

        <label>
          <Field
            name="sex"
            component={renderField}
            type="radio"
            value="male"
            checked={!this.props.disabledNext}
            onChange={this.passRadioValue}
          />{" "}
          Male
        </label>

        <div>
          <button type="submit" disabled={submitting}>
            Sign Up
          </button>
          <button
            type="button"
            disabled={(pristine || submitting) && this.state.pristine} //add state.pristine checking
            onClick={this.resetForm}
          >
            Clear Values
          </button>
        </div>
      </form>
    );
  }
}

Then, in StepTemplate.js Add disabledNext, checkDisabledNext props. checkDisabledNext to determine whether the Next Button will have conditional checking or not. disabledNext is the disabled value.

const StepTemplate = ({
  classes,
  canGoBack,
  canGoForward,
  onBack,
  onNext,
  text,
  children,
  //we pass down these 2 values
  disabledNext,
  checkDisabledNext
}) => (
  <Fragment>
    <Typography>{text}</Typography>

    <div className={classes.actionsContainer}>
      <div>
        {children}

        <Button
          disabled={!canGoBack}
          onClick={onBack}
          className={classes.button}
        >
          Back
        </Button>
        <Button
          variant="contained"
          color="primary"
          onClick={onNext}
          className={classes.button}
          //determine whether we should check button disabled or not
          disabled={checkDisabledNext ? disabledNext : false}
        >
          {canGoBack ? "Next" : "go to next step"}
        </Button>
      </div>
    </div>
  </Fragment>
);

This is Step1.js, here we just pass props to StepTemplate and AsyncValidationForm:

const Step = props => (
  <StepTemplate
    text={`
        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.

        For each ad campaign that you create, you can control how much you're
        willing to spend on clicks and conversions, which networks and
        geographical locations you want your ads to show on, and more.
    `}
    //we want to apply checking on Step1.js, so we add checkDisabledNext attribute
    checkDisabledNext={true}
    // disabledNext={this.props.disabledNext} //no need to do this because will be passed with  {...props} below
    {...props}
  >
    <form>
      form for the first step here
      <div>test here</div>
      <AsyncValidationForm
        onSubmit={values => {
          console.log(values);
          alert(
            `Values: username: ${values.username} password: ${values.password}`

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...