Использование Flutter Autocomplete TextField в качестве строки поиска со сложным вложением json - PullRequest
0 голосов
/ 27 апреля 2020

В настоящее время я использую флаттер 'Autocomplete TextField', чтобы создать панель поиска в моем приложении, которая ищет в сложном вложенном json, чтобы найти и отобразить его результаты. Сам файл json выглядит примерно так с точки зрения формата:

    [
      {
        "aisle":21,
        "foodType":"fruit",
        "types":[
          {
            "fruitName":"Lemon",
            "colour":"yellow",
          },
          {
            "fruitName":"Lime",
            "colour":"green",
          },
          {
            "fruitName":"Orange",
            "colour":"orange",
          }
        ],
        "name":"Citrus",
      },
]

Моя цель - проанализировать все уровни структуры файла json и отобразить информацию на экране. , Каждая группа, то есть в данном случае тип пищи, будет иметь одинаковые проходы, типы продуктов и названия категорий. Каждый тип 'group' также будет иметь те же категории.

Пока что я создал файл конструктора класса dart, чтобы получить данные из файла json и добавить их в объект dart:

class Foods {
  int aisle;
  String foodType;
  List<Types> types;
  String name;

  Foods({
    this.aisle,
    this.foodType,
    this.types,
    this.name,
  });

  Foods.fromJson(Map jsonMap) {
    aisle = jsonMap['aisle'];
    foodType = jsonMap['foodType'];
    if (jsonMap['types'] != null) {
      types = List<Types>();
      jsonMap['types'].forEach((v) {
        types.add(Types.fromJson(v));
      });
    }
    name = jsonMap['name'];
  }
} 

class Types {
  String fruitName;
  String colour;

  Types({
    this.fruitName,
    this.colour,
  });

  Types.fromJson(Map jsonMap) {
    fruitName = jsonMap['fruitName'];
    colour = jsonMap['colour'];
  }
} 

class FoodsViewModel {
  static List<Foods> foods;

  static Future loadFoods() async {
    try {
      foods = List<Foods>();
      String jsonString =
          await rootBundle.loadString('assets/data/foods.json');
      Map parsedJson = json.decode(jsonString);
      var categoryJson = parsedJson['Foods'] as List;
      for (int i = 0; i < categoryJson.length; i++) {
        foods.add(Foods.fromJson(categoryJson[i]));
      }
    } catch (e) {
      print(e);
    }
  }
}

Он содержит класс для каждой общей группы продуктов питания, класс для каждого типа ребенка в группе, а также модель, содержащую функцию Future / asyn c, вызывающую данные в приложение. Эта информация используется панелью поиска в приложении следующим образом:

  int aisle = 0;
  String foodType = 'Food Type';
  String fruitName = 'Fruit Name';
  String colour = 'Colour;

  @override
  void initState() {
    super.initState();
    _isSearching = false;
    _searchBarController = TextEditingController();
    GlobalKey<AutoCompleteTextFieldState<Foods>> key = GlobalKey();
    _searchBarController.addListener(() {
      setState(() {
        _searchKeyword = _searchBarController.text;
      });
    });
    _loadFoods();
    _searchTextField = AutoCompleteTextField<Foods>(
      controller: _searchBarController,
      decoration: InputDecoration(
        hintText: 'Find your food here...',
        border: InputBorder.none,
        fillColor: Colors.white,
        contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
        filled: true,
      ),
      itemBuilder: (context, item) {
        return Padding(
          padding: EdgeInsets.only(
            top: 5.0,
            left: 10.0,
            right: 10.0,
            bottom: 5.0,
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Text(
                item.foodType,
                style: kSearchBarTextStyle,
              ),
              SizedBox(height: 2.0),
              Row(
                children: <Widget>[
                  Text(
                    item.fruitName,
                    style: kSectionSubtitleTextStyle,
                  ),
                  SizedBox(width: 10.0),
                  Text(
                    item.colour,
                    style: kSectionSubtitleTextStyle,
                  ),
                ],
              ),
              SizedBox(height: 2.0),
              Row(
                children: <Widget>[
                  Text(
                    item.aisle.toString(),
                    style: kSectionSubtitleTextStyle,
                  ),
                ],
              ),
            ],
          ),
        );
      },
      itemFilter: (item, query) {
        return item.searchTerm.toLowerCase().contains(query.toLowerCase());
      },
      itemSorter: (a, b) {
        return a.name.compareTo(b.name);
      },
      itemSubmitted: (item) {
        setState(() {
          _searchTextField.textField.controller.text = item.foodType;
          aisle = item.aisle;
          foodType = item.foodType;
          fruitName = item.fruitName;
          colour = item.colour;
        });
      },
      key: key,
      suggestions: FoodsViewModel.foods,
      clearOnSubmit: false,
    );
  }

То, что я пробовал выше, похоже, только для получения данных верхнего уровня из файла json, который включает в себя проход , тип и название еды. Для категорий внутри потомков 'type' я получаю ошибку:

The getter 'fruitName' isn't defined for the class 'Foods'.

Как мне отредактировать написанный мной код, чтобы иметь возможность читать данные json в 'type' ( детские) группы? В идеале, я бы смог найти в строке поиска, скажем, тип пищи, а затем в раскрывающемся списке предложений будут указаны названия разных фруктов этого типа. Итак, если я найду

Citrus

, то получится список

Lemon
Lime
Orange

Или, если бы я искал

Lemon

, это просто придумал бы

Lemon

Есть ли способ изменить код, чтобы разрешить импорт группы дочерних типов и позволить их найти с помощью функции поиска? Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...