Taro UI realizes three-level linkage of provincial and urban areas

Posted by robindean on Fri, 19 Jun 2020 10:22:02 +0200

Because the taro UI does not have provincial and urban three-level linkage, we use the Picker provided by it to realize multi column selector.

<Picker
            mode="multiSelector" // Multi column selection
            onChange={this.onChange} // change event
            onColumnChange={this.onColumnChange} // Changed events in a column
            range={rangeData} //Data to show
            value={rangeKey} // Selected Subscripts
          >
            <View className="picker">
              <Text className="label">Address:</Text>
              {formData.province && (
                <Text>
                  {formData.province}
                  {formData.city}
                  {formData.country}
                </Text>
              )} // It is mainly the code of data echo plus,
              {!formData.province && (
                <Text className="placeholder">Please select a province/city/area</Text>
              )}
            </View>
          </Picker>

In fact, the above code has specific examples in the official taro UI documents, which will not be explained here.

I believe that the structure of each province and city is different. Now I post some of the province and city structures of my own project

[{
	provinceName: 'Beijing',
	provinceCode: '11',
	cities: [
	{
	cityName: 'Municipal District',
	cityCode: '1101',
	countries: [
		{
			countryCode: "110101"
			countryName: "Dongcheng District"
		}
		]
	}
	]
}]

Now we start to process the data, because rangeData is all data, province and city. We need to convert the data into ['province ',' city ',' District].

handleCityData = key => {
    // Process data.
    let provinceList = new Array(); // province
    let cityList = new Array(); // city
    let areaList = new Array(); // area
    let { addressData } = this.state;
    for (let i = 0; i < addressData.length; i++) {
      // Acquisition Province
      let province = addressData[i];
      provinceList.push(province.provinceName);
    }
    if (addressData[key[0]].cities && addressData[key[0]].cities.length > 0) {
      for (let i = 0; i < addressData[key[0]].cities.length; i++) {
        // Get the city under the corresponding province
        let city = addressData[key[0]].cities[i];
        cityList.push(city.cityName);
      }
    }
    for (
      let i = 0;
      i < addressData[key[0]].cities[key[1]].countries.length;
      i++
    ) {
      // Get the corresponding area under the city
      let country = addressData[key[0]].cities[key[1]].countries[i];
      areaList.push(country.countryName);
    }
    // }
    let newRange = new Array();
    newRange.push(provinceList);
    newRange.push(cityList);
    newRange.push(areaList);
    this.setState({
      rangeData: newRange, // All data of provincial and urban areas
      rangeKey: key // key is the subscript to be displayed by multi column selector. Because it is initialization, we passed in [0,0,0]
    });
  };

The data processing code is a little ugly. Welcome to give your comments. Since babel has not been upgraded to version 7, if judgment is a bit cumbersome.

After the data is processed, we need to start to process the value change of each column. If the data is linked, then we need the column linkage event.

onColumnChange = e => {
    let { rangeKey } = this.state;
    let changeColumn = e.detail;
    let { column, value } = changeColumn;
    switch (column) { // Display different data according to different columns
      case 0:
        this.handleCityData([value, 0, 0]);
        break;
      case 1:
        this.handleCityData([rangeKey[0], value, 0]);
        break;
      case 2:
        this.handleCityData([rangeKey[0], rangeKey[1], value]);
        break;
    }
  };

If we get here, we will basically realize the three-level linkage between the provincial and urban areas.

Let's talk about yiha, the code of data echo in provincial and urban areas. You can also understand yiha if you don't need it.
Data echo, in fact, is very simple, as long as you find the corresponding province and city subscript, you can echo. The following is the specific implementation code:

getRangeKey = data => {
    // Obtain the corresponding display location when the details are available
    let { addressData } = this.state;
    let splitData = data.addressDescription.split("|");

    let getAddress = {
      province: splitData[0],
      city: splitData[1],
      country: splitData[2]
    };
    this.setState({
      formData: getAddress
    });
    let provinceIndex = 0;
    let cityIndex = 0;
    let countryIndex = 0;
    for (let i = 0; i < addressData.length; i++) {
      let province = addressData[i];
      if (province.provinceName === getAddress.province) {
        provinceIndex = i;
        for (let j = 0; j < province.cities.length; j++) {
          let city = province.cities[j];
          if (city.cityName === getAddress.city) {
            cityIndex = j;
            for (let k = 0; k < city.countries.length; k++) {
              let country = city.countries[k];
              if (country.countryName === getAddress.country) {
                countryIndex = k;
                break;
              }
            }
            break;
          }
        }
        break;
      }
    }
    let rangeKey = new Array();
    rangeKey.push(provinceIndex);
    rangeKey.push(cityIndex);
    rangeKey.push(countryIndex);
    this.handleCityData(rangeKey);
  };

Through the above cycle to find out the subscript of the corresponding province and city, we can achieve the data echo of the province and city.

Oh, I also forget the change event of multi column selector. In this case, code or name will be returned according to the needs of my project, which will be handled by myself. I'm talking about the three-level linkage of provincial and urban areas.
I write the provincial and urban areas as a component, and then pass in the corresponding data and events in the parent node, which can be used multiple times in a project.