fetchFieldOptions method

Future<void> fetchFieldOptions(
  1. Field field,
  2. Map<String, dynamic> formValues
)

Implementation

Future<void> fetchFieldOptions(
    Field field, Map<String, dynamic> formValues) async {
  if (field.source == null) return;
  if (optionsInProgress[field.name] == true) return;

  optionsInProgress[field.name] = true;

  Source source = field.source!;
  String? url = source.api;
  final labelKey = source.labelKey ?? 'name';
  final valueKey = source.valueKey ?? 'id';
  final staticOptions = source.options ?? [];
  final alwaysRefresh = source.alwaysRefresh ?? false;

  bool shouldFetch =
      !(options.containsKey(field.name) && options[field.name]!.isNotEmpty);
  bool dependenciesMissing = false;
  // Handle dependencies
  if (field.dependentOn != null && field.dependentOn!.isNotEmpty) {
    for (final dep in field.dependentOn!) {
      final val = formValues[dep];
      final last = dependentValues[field.name]?[dep];

      if ((val == null || val.toString().isEmpty) &&
          !(url?.contains("page=") ?? false)) {
        dependenciesMissing = true;
      }
      if (val != last) {
        shouldFetch = true;
        dependentValues[field.name] = {
          ...(dependentValues[field.name] ?? {}),
          dep: val,
        };
      }
    }
  }

  if (url != null) {
    url = replaceUrlPlaceholders(url, formValues);
  }

  if (dependenciesMissing || (!shouldFetch && !alwaysRefresh)) {
    optionsInProgress[field.name] = false;
    notifyListeners();
    return;
  }

  if (url != null && url.isNotEmpty) {
    try {
      final response = await httpClient?.get(url);
      if (response?.statusCode == 200) {
        final jsonData = response?.data;
        final List dataList = jsonData['result'] ??
            jsonData['data'] ??
            jsonData['results'] ??
            [];

        List<Option> newOptions = dataList
            .map<Option>((item) => Option(
                  label: item[labelKey].toString(),
                  value: item[valueKey],
                  item: item is Map<String, dynamic>
                      ? item
                      : Map<String, dynamic>.from(item),
                ))
            .toList();

        setFieldOptions(field.name, newOptions);

        if (field.autoFill != null) {
          handleAutoFill(field);
        }
      } else {
        throw Exception("Failed to fetch options for ${field.name}");
      }
    } catch (e) {
      setFieldOptions(field.name, []);
    }
  } else if (staticOptions.isNotEmpty) {
    setFieldOptions(field.name, staticOptions);

    if (field.autoFill != null) {
      handleAutoFill(field);
    }
  }
  optionsInProgress[field.name] = false;
  notifyListeners();
}