首页 >web前端 >js教程 >级联表单 React Native 高级

级联表单 React Native 高级

DDD
DDD原创
2024-12-08 13:00:181003浏览

我想分享我处理级联表单字段的 3 种方法。

  1. 第一种方法是通用的,使用状态变量。
  2. 第二种是使用普通变量和一个布尔状态变量来触发状态效果(刷新页面)。
  3. 第三种是带有普通变量的动态表单字段。

这是第三种方法,我们将处理动态表单字段。

注意,如果你看看前面的两种方法,会更容易理解这篇文章。

第一种方法,Cascade Form Basic
第二种方法,改进级联形式

我们开始吧,

内容

  • 基本形式
  • 表单字段对象
  • 动态场渲染
  • 示例数据
  • 页面加载
  • 加载国家
  • OnChange
  • 加载状态
  • 负载休息(城市、村庄、街道)
  • 验证
  • 重置表格

基本形式

这是带有 5 个下拉字段的静态表单页面。

import React, { useState, useEffect } from "react";
import { ScrollView, View, Text, StyleSheet, TouchableOpacity } from "react-native";
import { Dropdown } from "react-native-element-dropdown";
import { Snackbar } from "react-native-paper";

var snackMsg = "";
export default function App() {
  const [refreshPage, setRefreshPage] = useState(false);
  const [visible, setVisible] = useState(false);

  const onToggleSnackBar = () => setVisible(!visible);
  const onDismissSnackBar = () => setVisible(false);

  const resetForm = () => {
  };

  return (
    <ScrollView>



<p>refreshPage state variable is used to refresh the page in all the situations. </p>

<p><img src="https://img.php.cn/upload/article/000/000/000/173363402014343.jpg" alt="Cascading Form React Native Advanced" /></p>

<p>Now, These fields are going to be converted as dynamic. </p>

<h3>
  
  
  Form Field Object
</h3>

<p>Previously we had 3 separate objects for 3 different fields, but here all fields data placed under one form field object.<br>
</p>

<pre class="brush:php;toolbar:false"> . . .
const formFields = {
  country: {
    fieldId: "country",
    label: "Country",
    labelField: "name",
    valueField: "countryId",
    parents: [],
    list: [],
    selectedItem: {},
    selectedValue: null,
    onValueSelected: () => null,
  },
  state: {
    fieldId: "state",label: "State",labelField: "name",valueField: "stateId",
    parents: ["country"],list: [],selectedItem: {},selectedValue: null,
    onValueSelected: () => null,
  },
  city: {
    fieldId: "city",label: "City",labelField: "name",valueField: "cityId",
    parents: ["country", "state"],list: [],selectedItem: {},
    selectedValue: null,onValueSelected: () => null,
  },
  village: {
    fieldId: "village",label: "Village",labelField: "name",
    valueField: "villageId",
    parents: ["country", "state", "city"],
    list: [],selectedItem: {},selectedValue: null,
    onValueSelected: () => null,
  },
  street: {
    fieldId: "street",label: "Street",labelField: "name",
    valueField: "streetId",
    parents: ["country", "state", "city", "village"],
    list: [],selectedItem: {},selectedValue: null,onValueSelected: () => null,
  },
};

 . . .
export default function App() {
   . . .
}

字段的所有这些属性都有好处,对于处理动态渲染将很有用。

  • fieldId 字段 ID
  • label 显示字段名称
  • labelField 表示下拉列表数组中的下拉标签字段
  • valueField 表示下拉值字段
  • 父字段的parents 数组,将用于验证
  • 列表下拉列表数组
  • selectedItem 下拉列表的整个选定项目对象
  • selectedValue 所选值
  • onValueSelected 它是一个函数属性,当选择/更改下拉值时将使用/调用。最初分配为空方法。

动态场渲染

通过迭代表单字段对象键,我们动态渲染下拉字段,所有必需的属性都可以在表单字段对象中使用。

export default function App() {
  . . .
    return (
    <View>



<p>handle focus / blur<br>
</p>

<pre class="brush:php;toolbar:false">var focusField = "";
export default function App() {
. . .

 const changeFocusField = (fld = "") => {
  focusField = fld;
  setRefreshPage(!refreshPage);
 };
. . .
}
<ZDropDown
. . .
  isFocus={focusField === ele}
  onFocus={() => {
    changeFocusField(ele);
  }}
  onBlur={() => changeFocusField("")}
  onChange={(item) => {}}
 />

样本数据

国家、州、城市、村庄和街道字段的示例数据。

const listCountry = [
  { countryId: "1", name: "india" },
  { countryId: "2", name: "uk" },
  { countryId: "3", name: "canada" },
  { countryId: "4", name: "us" },
];

const listSate = [
  { stateId: "1", countryId: "1", name: "state1_india" },
  { stateId: "4", countryId: "2", name: "state1_uk" },
  { stateId: "7", countryId: "3", name: "state1_canada" },
  { stateId: "10", countryId: "4", name: "state1_us" },
];

const listCity = [
  { cityId: "1", stateId: "1", countryId: "1", name: "city1_state1_country1" },
  { cityId: "5", stateId: "2", countryId: "1", name: "city5_state2_country1" },
  {
    cityId: "21",stateId: "7",countryId: "3",name:"city21_state7_country3",
  },
  {
    cityId: "26",stateId: "9",countryId: "3",name: "city26_state9_country3",
  },
];

const listVillage = [
  { cityId: "1", villageId: "1", name: "village 1  city 1" },
  { cityId: "2", villageId: "5", name: "village 5  city 2" },
  { cityId: "3", villageId: "9", name: "village 9  city 3" },
  { cityId: "4", villageId: "10", name: "village 10  city 4" },
];

const listStreet = [
  { villageId: "1", streetId: "1", name: "village 1 street 1" },
  { villageId: "1", streetId: "109", name: "village 1 street 109" },
  { villageId: "2", streetId: "2", name: "village 2 street 2" },
  { villageId: "2", streetId: "110", name: "village 2 street 110" },
];
 . . .
export default function App() {
  . . .
}
 . . .

页面加载

首先在功能方面我们必须设置一些重要的东西。 请记住,我们为 onValueSelected 属性分配了一个空方法,现在是时候分配实际方法了。因此我们需要创建 5 个方法并将它们分配给各自的表单字段。

export default function App() {
  . . .
  const allValuesSelected = () => {
    console.log("All fields value selected");
  };

  const loadStreet = async () => {};

  const loadVillage = async () => {};

  const loadCity = async () => {};

  const loadState = async () => {};

  const loadCountry = async () => {};

  const loadPageData = () => {
    formFields.country.onValueSelected = loadState;
    formFields.state.onValueSelected = loadCity;
    formFields.city.onValueSelected = loadVillage;
    formFields.village.onValueSelected = loadStreet;
    formFields.street.onValueSelected = allValuesSelected;    
  };

  return (. . .);
}

当选择 Country 值时,必须加载 STATE 列表,这就是为什么这里将 loadState 方法分配给 Country 的 onValueSelected。同样分配了其他方法。

  useEffect(() => {
    loadPageData();
  }, []);

  return (. . .);

负载国家

从示例数据加载国家/地区列表并在初始页面加载时调用它。

  const loadCountry = async () => {
    formFields.country.list = [...listCountry];
    setRefreshPage(!refreshPage);
  };

  const loadPageData = () => {
    formFields.country.onValueSelected = loadState;
    formFields.state.onValueSelected = loadCity;
    formFields.city.onValueSelected = loadVillage;
    formFields.village.onValueSelected = loadStreet;
    formFields.street.onValueSelected = allValuesSelected;

    loadCountry();
  };

变化时

选择下拉字段值后,我们需要设置相应的表单字段值,移除焦点并加载下一个下拉列表。

return (
  . . .
  <ZDropDown
    // . . .
    onChange={(item) => {
      fld.selectedItem = item;
      fld.selectedValue = item[fld.valueField];
      focusField = "";
      fld.onValueSelected();
    }}
  />
  . . .
);

onValueSelected 很有用吧?

负载状态

当第一个下拉列表(国家/地区)更改时,其余字段将发生更改。因此需要清除所有其他表单字段的列表和数据。为此,我们编写了一个方法,可以清除给定字段到结束字段的值。

import React, { useState, useEffect } from "react";
import { ScrollView, View, Text, StyleSheet, TouchableOpacity } from "react-native";
import { Dropdown } from "react-native-element-dropdown";
import { Snackbar } from "react-native-paper";

var snackMsg = "";
export default function App() {
  const [refreshPage, setRefreshPage] = useState(false);
  const [visible, setVisible] = useState(false);

  const onToggleSnackBar = () => setVisible(!visible);
  const onDismissSnackBar = () => setVisible(false);

  const resetForm = () => {
  };

  return (
    <ScrollView>



<p>refreshPage state variable is used to refresh the page in all the situations. </p>

<p><img src="https://img.php.cn/upload/article/000/000/000/173363402014343.jpg" alt="Cascading Form React Native Advanced" /></p>

<p>Now, These fields are going to be converted as dynamic. </p>

<h3>
  
  
  Form Field Object
</h3>

<p>Previously we had 3 separate objects for 3 different fields, but here all fields data placed under one form field object.<br>
</p>

<pre class="brush:php;toolbar:false"> . . .
const formFields = {
  country: {
    fieldId: "country",
    label: "Country",
    labelField: "name",
    valueField: "countryId",
    parents: [],
    list: [],
    selectedItem: {},
    selectedValue: null,
    onValueSelected: () => null,
  },
  state: {
    fieldId: "state",label: "State",labelField: "name",valueField: "stateId",
    parents: ["country"],list: [],selectedItem: {},selectedValue: null,
    onValueSelected: () => null,
  },
  city: {
    fieldId: "city",label: "City",labelField: "name",valueField: "cityId",
    parents: ["country", "state"],list: [],selectedItem: {},
    selectedValue: null,onValueSelected: () => null,
  },
  village: {
    fieldId: "village",label: "Village",labelField: "name",
    valueField: "villageId",
    parents: ["country", "state", "city"],
    list: [],selectedItem: {},selectedValue: null,
    onValueSelected: () => null,
  },
  street: {
    fieldId: "street",label: "Street",labelField: "name",
    valueField: "streetId",
    parents: ["country", "state", "city", "village"],
    list: [],selectedItem: {},selectedValue: null,onValueSelected: () => null,
  },
};

 . . .
export default function App() {
   . . .
}

此方法可用于所有其他下拉字段和页面重置目的。

export default function App() {
  . . .
    return (
    <View>



<p>handle focus / blur<br>
</p>

<pre class="brush:php;toolbar:false">var focusField = "";
export default function App() {
. . .

 const changeFocusField = (fld = "") => {
  focusField = fld;
  setRefreshPage(!refreshPage);
 };
. . .
}

状态下拉列表现已完美加载。

加载其余部分(城市、村庄、街道)

就像之前一样,我们加载其余字段的数据。

<ZDropDown
. . .
  isFocus={focusField === ele}
  onFocus={() => {
    changeFocusField(ele);
  }}
  onBlur={() => changeFocusField("")}
  onChange={(item) => {}}
 />

很好,所有下拉菜单都填充了各自的列表。

Cascading Form React Native Advanced

验证

在显示下拉列表之前,我们需要验证其父字段。因此,我们将从表单字段对象中获取父字段。然后逐一迭代它们,验证其值并在必要时显示警告。

const listCountry = [
  { countryId: "1", name: "india" },
  { countryId: "2", name: "uk" },
  { countryId: "3", name: "canada" },
  { countryId: "4", name: "us" },
];

const listSate = [
  { stateId: "1", countryId: "1", name: "state1_india" },
  { stateId: "4", countryId: "2", name: "state1_uk" },
  { stateId: "7", countryId: "3", name: "state1_canada" },
  { stateId: "10", countryId: "4", name: "state1_us" },
];

const listCity = [
  { cityId: "1", stateId: "1", countryId: "1", name: "city1_state1_country1" },
  { cityId: "5", stateId: "2", countryId: "1", name: "city5_state2_country1" },
  {
    cityId: "21",stateId: "7",countryId: "3",name:"city21_state7_country3",
  },
  {
    cityId: "26",stateId: "9",countryId: "3",name: "city26_state9_country3",
  },
];

const listVillage = [
  { cityId: "1", villageId: "1", name: "village 1  city 1" },
  { cityId: "2", villageId: "5", name: "village 5  city 2" },
  { cityId: "3", villageId: "9", name: "village 9  city 3" },
  { cityId: "4", villageId: "10", name: "village 10  city 4" },
];

const listStreet = [
  { villageId: "1", streetId: "1", name: "village 1 street 1" },
  { villageId: "1", streetId: "109", name: "village 1 street 109" },
  { villageId: "2", streetId: "2", name: "village 2 street 2" },
  { villageId: "2", streetId: "110", name: "village 2 street 110" },
];
 . . .
export default function App() {
  . . .
}
 . . .

Cascading Form React Native Advanced

重置表格

最后,我们提供了重置表单字段的选项。

export default function App() {
  . . .
  const allValuesSelected = () => {
    console.log("All fields value selected");
  };

  const loadStreet = async () => {};

  const loadVillage = async () => {};

  const loadCity = async () => {};

  const loadState = async () => {};

  const loadCountry = async () => {};

  const loadPageData = () => {
    formFields.country.onValueSelected = loadState;
    formFields.state.onValueSelected = loadCity;
    formFields.city.onValueSelected = loadVillage;
    formFields.village.onValueSelected = loadStreet;
    formFields.street.onValueSelected = allValuesSelected;    
  };

  return (. . .);
}

全部完成。现在我们看到了如何处理动态表单字段、呈现字段、加载数据并验证它们。

这是我处理级联表单字段的 3 种方法。

希望这篇文章/系列有一些您喜欢的有用的东西。谢谢。

完整代码在这里

以上是级联表单 React Native 高级的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn