Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/412.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Antd选择表单项键盘行为问题_Javascript_Reactjs_Antd - Fatal编程技术网

Javascript Antd选择表单项键盘行为问题

Javascript Antd选择表单项键盘行为问题,javascript,reactjs,antd,Javascript,Reactjs,Antd,我有一个表格,在大多数情况下都很好用。但有一件事让我感到不安,那就是用于输入一个人状态的选择项(见下面的屏幕截图)。它可以很好地使用鼠标,但是如果您在表单中使用tab键,并将tab键指向State字段,然后键入一个类似加州的州,然后将tab键指向下一个字段zipcode,State字段将重置为空白。如果它与选择器的一个选项匹配,我希望它继续填充CA 如果我键入CA并按enter键前进到下一个字段,它确实可以工作,但这似乎并不能直观地了解表单的正常工作方式。如果我只使用鼠标选择字段,它也可以工作。

我有一个表格,在大多数情况下都很好用。但有一件事让我感到不安,那就是用于输入一个人状态的选择项(见下面的屏幕截图)。它可以很好地使用鼠标,但是如果您在表单中使用tab键,并将tab键指向State字段,然后键入一个类似加州的州,然后将tab键指向下一个字段zipcode,State字段将重置为空白。如果它与选择器的一个选项匹配,我希望它继续填充CA

如果我键入CA并按enter键前进到下一个字段,它确实可以工作,但这似乎并不能直观地了解表单的正常工作方式。如果我只使用鼠标选择字段,它也可以工作。我一直在查看Select上的antd文档,没有看到任何可以控制这一点的东西。也许我遗漏了什么,我需要做一些onchange函数

不管怎么说,这似乎是一个相当简单的问题,但解决办法是我逃避

选择表单项的代码:

艾尔 AK 阿兹 应收账 加利福尼亚州 一氧化碳 计算机断层扫描 判定元件 佛罗里达州 GA 你好 身份证件 白细胞介素 在里面 IA KS 基尼 洛杉矶 我 医学博士 文科硕士 医疗保险 锰 太太 卫生官员 机器翻译 氖 内华达州 全日空航空公司 新泽西州 纳米 纽约 数控 钕 哦 好啊 或 帕 RI 联合国安全理事会 SD 总氮 德克萨斯州 美国犹他州 及物动词 弗吉尼亚州 华盛顿州 WV WI WY 像 直流 调频 顾 MH 议员 嗯 公共关系 不及物动词 更新1

因此,根据评论中的建议和我在表单控制部分下注意到的类似方法,我在我的类中添加了一个formRef=React.createRef

然后在我的表单标记中添加了一个ref={this.formRef}标记。然后通过添加onBlur标记修改了我的选择,该标记触发setFieldsValue以设置输入的大写版本

这可以很好地编译和运行。它甚至输出console.log语句。但由于某种原因,它没有设置字段值,我也不知道为什么

回来 { {fields,{add,remove}=>{ 回来 {fields.mapfield,索引=> { **console.logonblur:,事件; **this.formRef.current.setFieldsValue{state:event.target.value.toUpperCase}; ** }} > 更新2

调用onFinish时值的屏幕截图。注意,这是一个动态表单,用户可以通过单击“添加申请者”按钮添加其他申请者。每个申请者都有显示的字段,包括他们居住的州

    const onFinish = (values) => {
      console.log("onFinish: ", values);
      this.props.onSubmit({
        applicants: values.applicants,
      });
    };
更新3

试图模仿这种方法,但是由于某些原因,在由值返回的对象中,状态不存在,最终我得到一个未捕获的typeerror,并且状态不填充

更新4

因此,可以肯定的是,移除表单标记中的name属性解决了上述问题,并且按照预期工作,没有出现错误

为了收尾 这个问题希望它能帮助其他人,我想捕获解决方案。最终,解决方案相当于这样做,当用户从有问题的字段中签出时,字段的值设置为用户键入的值。这是通过将onBlur标记添加到我的antd Select标记来完成的。onBlur在用户将选项卡移出字段时激发。然后将字段设置为输入的字符。由于使用了动态表单和嵌套对象数组,结果比我想象的要复杂

注意,状态现在显示在value下,namepath与代码期望的匹配

到目前为止,我的最终代码如下所示

import React from "react";
import { Form, Input, Col, Row, Select, Button } from "antd";
import { PlusOutlined, MinusCircleTwoTone } from "@ant-design/icons";

const InputGroup = Input.Group;
const Option = Select.Option;
const { TextArea } = Input;
const maxApplicants = 4;

const rules = [{ required: true }];

const STATES = [
  "AL",
  "AK",
  "AZ",
  "AR",
  "CA",
  "CO",
  "CT",
  "DE",
  "DC",
  "FM",
  "FL",
  "GA",
  "GU",
  "HI",
  "ID",
  "IL",
  "IN",
  "IA",
  "KS",
  "KY",
  "LA",
  "ME",
  "MH",
  "MD",
  "MA",
  "MI",
  "MN",
  "MS",
  "MO",
  "MT",
  "NE",
  "NV",
  "NH",
  "NJ",
  "NM",
  "NY",
  "NC",
  "ND",
  "MP",
  "OH",
  "OK",
  "OR",
  "PW",
  "PA",
  "PR",
  "RI",
  "SC",
  "SD",
  "TN",
  "TX",
  "UT",
  "VT",
  "VI",
  "VA",
  "WA",
  "WV",
  "WI",
  "WY",
];

const validateMessages = {
  required: "Required!",
  types: {
    email: "Invalid E-mail!",
    number: "Invalid Number!",
  },
  number: {
    range: "Must be between ${min} and ${max}",
  },
};

const formItemLayout = {
  labelCol: {
    xs: { span: 24 },
    sm: { span: 6 },
  },
  wrapperCol: {
    xs: { span: 36 },
    sm: { span: 16 },
  },
};

const formItemLayoutWithOutLabel = {
  wrapperCol: {
    xs: { span: 36, offset: 0 },
    sm: { span: 16, offset: 6 },
  },
};

export default class TenantForm extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      applicants: [
        {
          firstName: props.tenant ? props.tenant.first : "",
          middleName: props.tenant ? props.tenant.middle : "",
          lastName: props.tenant ? props.tenant.last : "",
          street: props.tenant ? props.tenant.street : "",
          city: props.tenant ? props.tenant.city : "",
          state: props.tenant ? props.tenant.state : "",
          zipcode: props.tenant ? props.tenant.zipcode : "",
        },
      ],
      error: "",
    };
  }

  formRef = React.createRef();

  render() {
    const onFinish = (values) => {
      console.log("onFinish: ", values);
      this.props.onSubmit({
        applicants: values.applicants,
      });
    };

    return (
      <Form
        ref={this.formRef}
        {...formItemLayoutWithOutLabel}
        onFinish={onFinish}
        id="myForm"
        validateMessages={validateMessages}
        initialValues={{ applicants: [{ firstName: "" }] }}
      >
        {
          <Form.List name="applicants">
            {(fields, { add, remove }) => {
              return (
                <div>
                  {fields.map((field, index) => (
                    <Form.Item {...formItemLayout} label={`Applicant #${index + 1}`} key={field.key}>
                      <Row key={field.key} gutter={[0, 8]} justify="start">
                        <Col>
                          <Row gutter={[4, 4]}>
                            <Col span={7}>
                              <Form.Item name={[field.name, "firstName"]} fieldKey={[field.fieldKey, "firstName"]} rules={rules}>
                                <Input placeholder="First Name" />
                              </Form.Item>
                            </Col>
                            <Col span={7}>
                              <Form.Item name={[field.name, "middleName"]} fieldKey={[field.fieldKey, "middleName"]} initialValue="">
                                <Input placeholder="Middle Name" />
                              </Form.Item>
                            </Col>
                            <Col span={9}>
                              <Form.Item name={[field.name, "lastName"]} fieldKey={[field.fieldKey, "lastName"]} rules={rules}>
                                <Input placeholder="Last Name" />
                              </Form.Item>
                            </Col>
                            <Col flex="none">
                              {index > 0 ? (
                                <MinusCircleTwoTone
                                  className="dynamic-delete-button"
                                  onClick={() => {
                                    remove(field.name);
                                  }}
                                />
                              ) : null}
                            </Col>
                          </Row>
                          <Row gutter={[4, 4]}>
                            <Col span={23}>
                              <Form.Item name={[field.name, "address"]} fieldKey={[field.fieldKey, "address"]} rules={rules}>
                                <Input placeholder="Address" />
                              </Form.Item>
                            </Col>
                          </Row>
                          <Row gutter={[4, 4]}>
                            <Col span={12}>
                              <Form.Item name={[field.name, "city"]} fieldKey={[field.fieldKey, "city"]} rules={rules}>
                                <Input placeholder="City" />
                              </Form.Item>
                            </Col>
                            <Col span={5}>
                              <Form.Item name={[field.name, "state"]} fieldKey={[field.fieldKey, "state"]} rules={rules}>
                                <Select
                                  showSearch
                                  placeholder="State"
                                  defaultActiveFirstOption={true}
                                  onBlur={(event) => {
                                    console.log("values", this.formRef.current.getFieldsValue());
                                    console.log("target:", event.target);
                                    console.log("id", event.target.id);
                                    const stateIndex = event.target.getAttribute("aria-activedescendant").split("_").slice(-1);
                                    const values = this.formRef.current.getFieldsValue();
                                    const namePath = event.target.id.split("_");
                                    console.log("namePath", namePath);
                                    values[namePath[0]][namePath[1]][namePath[2]] = event.target.value.toUpperCase() || STATES[stateIndex];
                                    this.formRef.current.setFieldsValue(values);
                                  }}
                                >
                                  {STATES.map((state) => (
                                    <Option value={state} key={state}>
                                      {state}
                                    </Option>
                                  ))}
                                </Select>
                              </Form.Item>
                            </Col>
                            <Col span={6}>
                              <Form.Item name={[field.name, "zipcode"]} fieldKey={[field.fieldKey, "zipcode"]} rules={rules}>
                                <Input placeholder="Zip Code" />
                              </Form.Item>
                            </Col>
                          </Row>
                        </Col>
                      </Row>
                    </Form.Item>
                  ))}
                  <Form.Item>
                    {console.log("count:", fields.length)}
                    {fields.length < maxApplicants ? (
                      <Button
                        type="dashed"
                        onClick={() => {
                          add();
                        }}
                        style={{ width: "100%" }}
                      >
                        <PlusOutlined /> Add Applicant
                      </Button>
                    ) : null}
                  </Form.Item>
                </div>
              );
            }}
          </Form.List>
        }
      </Form>
    );
  }
}

诀窍是结合form.setFieldsValue在Select组件上使用onBlur

请参见下面的codesandbox:

它在类组件中的工作方式相同,但您可以通过ref:formRef=React.createRef;请参阅第24行和第49行:如果我的答案对您有所帮助,请您将我的答案标记为有用,我将不胜感激。干杯在onFinish处理程序中,您可以控制台.log值并发布结果。我认为state字段设置不正确,因为state不是values对象内部的顶级属性。此名称={[field.name,state]}似乎表示状态嵌套在计算结果为field.name.Updated的动态表单解决方案的属性中:是否可以包含包含表单和表单.List组件的代码块?看起来您可能在这两个组件中都定义了name prop,而且由于name值带有下划线,因此我的split方法无法工作。是 啊这会变得非常复杂,但幸运的是,一旦你保护了你想要的行为,你就可以将组件包装在一个HOC中,使行为在未来的组件中可重用。顺便说一句,如果你删除表单组件上的name prop,我想你当前实现我的方法的尝试会奏效。我很确定,如果您打算通过应用程序中其他地方的Form.Provider访问表单实例,您只需要为表单提供一个名称。
import React from "react";
import { Form, Input, Col, Row, Select, Button } from "antd";
import { PlusOutlined, MinusCircleTwoTone } from "@ant-design/icons";

const InputGroup = Input.Group;
const Option = Select.Option;
const { TextArea } = Input;
const maxApplicants = 4;

const rules = [{ required: true }];

const STATES = [
  "AL",
  "AK",
  "AZ",
  "AR",
  "CA",
  "CO",
  "CT",
  "DE",
  "DC",
  "FM",
  "FL",
  "GA",
  "GU",
  "HI",
  "ID",
  "IL",
  "IN",
  "IA",
  "KS",
  "KY",
  "LA",
  "ME",
  "MH",
  "MD",
  "MA",
  "MI",
  "MN",
  "MS",
  "MO",
  "MT",
  "NE",
  "NV",
  "NH",
  "NJ",
  "NM",
  "NY",
  "NC",
  "ND",
  "MP",
  "OH",
  "OK",
  "OR",
  "PW",
  "PA",
  "PR",
  "RI",
  "SC",
  "SD",
  "TN",
  "TX",
  "UT",
  "VT",
  "VI",
  "VA",
  "WA",
  "WV",
  "WI",
  "WY",
];

const validateMessages = {
  required: "Required!",
  types: {
    email: "Invalid E-mail!",
    number: "Invalid Number!",
  },
  number: {
    range: "Must be between ${min} and ${max}",
  },
};

const formItemLayout = {
  labelCol: {
    xs: { span: 24 },
    sm: { span: 6 },
  },
  wrapperCol: {
    xs: { span: 36 },
    sm: { span: 16 },
  },
};

const formItemLayoutWithOutLabel = {
  wrapperCol: {
    xs: { span: 36, offset: 0 },
    sm: { span: 16, offset: 6 },
  },
};

export default class TenantForm extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      applicants: [
        {
          firstName: props.tenant ? props.tenant.first : "",
          middleName: props.tenant ? props.tenant.middle : "",
          lastName: props.tenant ? props.tenant.last : "",
          street: props.tenant ? props.tenant.street : "",
          city: props.tenant ? props.tenant.city : "",
          state: props.tenant ? props.tenant.state : "",
          zipcode: props.tenant ? props.tenant.zipcode : "",
        },
      ],
      error: "",
    };
  }

  formRef = React.createRef();

  render() {
    const onFinish = (values) => {
      console.log("onFinish: ", values);
      this.props.onSubmit({
        applicants: values.applicants,
      });
    };

    return (
      <Form
        ref={this.formRef}
        {...formItemLayoutWithOutLabel}
        onFinish={onFinish}
        id="myForm"
        validateMessages={validateMessages}
        initialValues={{ applicants: [{ firstName: "" }] }}
      >
        {
          <Form.List name="applicants">
            {(fields, { add, remove }) => {
              return (
                <div>
                  {fields.map((field, index) => (
                    <Form.Item {...formItemLayout} label={`Applicant #${index + 1}`} key={field.key}>
                      <Row key={field.key} gutter={[0, 8]} justify="start">
                        <Col>
                          <Row gutter={[4, 4]}>
                            <Col span={7}>
                              <Form.Item name={[field.name, "firstName"]} fieldKey={[field.fieldKey, "firstName"]} rules={rules}>
                                <Input placeholder="First Name" />
                              </Form.Item>
                            </Col>
                            <Col span={7}>
                              <Form.Item name={[field.name, "middleName"]} fieldKey={[field.fieldKey, "middleName"]} initialValue="">
                                <Input placeholder="Middle Name" />
                              </Form.Item>
                            </Col>
                            <Col span={9}>
                              <Form.Item name={[field.name, "lastName"]} fieldKey={[field.fieldKey, "lastName"]} rules={rules}>
                                <Input placeholder="Last Name" />
                              </Form.Item>
                            </Col>
                            <Col flex="none">
                              {index > 0 ? (
                                <MinusCircleTwoTone
                                  className="dynamic-delete-button"
                                  onClick={() => {
                                    remove(field.name);
                                  }}
                                />
                              ) : null}
                            </Col>
                          </Row>
                          <Row gutter={[4, 4]}>
                            <Col span={23}>
                              <Form.Item name={[field.name, "address"]} fieldKey={[field.fieldKey, "address"]} rules={rules}>
                                <Input placeholder="Address" />
                              </Form.Item>
                            </Col>
                          </Row>
                          <Row gutter={[4, 4]}>
                            <Col span={12}>
                              <Form.Item name={[field.name, "city"]} fieldKey={[field.fieldKey, "city"]} rules={rules}>
                                <Input placeholder="City" />
                              </Form.Item>
                            </Col>
                            <Col span={5}>
                              <Form.Item name={[field.name, "state"]} fieldKey={[field.fieldKey, "state"]} rules={rules}>
                                <Select
                                  showSearch
                                  placeholder="State"
                                  defaultActiveFirstOption={true}
                                  onBlur={(event) => {
                                    console.log("values", this.formRef.current.getFieldsValue());
                                    console.log("target:", event.target);
                                    console.log("id", event.target.id);
                                    const stateIndex = event.target.getAttribute("aria-activedescendant").split("_").slice(-1);
                                    const values = this.formRef.current.getFieldsValue();
                                    const namePath = event.target.id.split("_");
                                    console.log("namePath", namePath);
                                    values[namePath[0]][namePath[1]][namePath[2]] = event.target.value.toUpperCase() || STATES[stateIndex];
                                    this.formRef.current.setFieldsValue(values);
                                  }}
                                >
                                  {STATES.map((state) => (
                                    <Option value={state} key={state}>
                                      {state}
                                    </Option>
                                  ))}
                                </Select>
                              </Form.Item>
                            </Col>
                            <Col span={6}>
                              <Form.Item name={[field.name, "zipcode"]} fieldKey={[field.fieldKey, "zipcode"]} rules={rules}>
                                <Input placeholder="Zip Code" />
                              </Form.Item>
                            </Col>
                          </Row>
                        </Col>
                      </Row>
                    </Form.Item>
                  ))}
                  <Form.Item>
                    {console.log("count:", fields.length)}
                    {fields.length < maxApplicants ? (
                      <Button
                        type="dashed"
                        onClick={() => {
                          add();
                        }}
                        style={{ width: "100%" }}
                      >
                        <PlusOutlined /> Add Applicant
                      </Button>
                    ) : null}
                  </Form.Item>
                </div>
              );
            }}
          </Form.List>
        }
      </Form>
    );
  }
}