searchable_dropdown_form_field 0.1.1 copy "searchable_dropdown_form_field: ^0.1.1" to clipboard
searchable_dropdown_form_field: ^0.1.1 copied to clipboard

A customizable, searchable Flutter dropdown with form validation and generic value support.

example/lib/main.dart

import 'package:searchable_dropdown_form_field/searchable_dropdown_form_field.dart';
import 'package:flutter/material.dart';

void main() => runApp(const ExampleApp());

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Searchable dropdown example',
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const ExamplePage(),
    );
  }
}

class ExamplePage extends StatefulWidget {
  const ExamplePage({super.key});

  @override
  State<ExamplePage> createState() => _ExamplePageState();
}

class _ExamplePageState extends State<ExamplePage> {
  final _formKey = GlobalKey<FormState>();
  String? _country;
  String? _remoteCountry;

  static const _countries = [
    DropdownItem(label: 'Bangladesh', value: 'BD'),
    DropdownItem(label: 'India', value: 'IN'),
    DropdownItem(label: 'Nepal', value: 'NP'),
    DropdownItem(label: 'Sri Lanka', value: 'LK'),
  ];

  Future<List<DropdownItem<String>>> _loadCountries(String query) async {
    await Future<void>.delayed(const Duration(milliseconds: 400));
    final normalizedQuery = query.toLowerCase();
    return _countries
        .where((item) => item.label.toLowerCase().contains(normalizedQuery))
        .toList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Searchable dropdown')),
      body: Form(
        key: _formKey,
        child: ListView(
          padding: const EdgeInsets.all(24),
          children: [
            CustomSearchableDropdown<String>(
              value: _country,
              dialogTitle: 'Select a country',
              hintText: 'Choose a country',
              decoration: InputDecoration(
                labelText: 'Country',
                helperText: 'Search and select your country',
                prefixIcon: const Icon(Icons.public),
                filled: true,
                fillColor: Theme.of(
                  context,
                ).colorScheme.surfaceContainerHighest,
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12),
                ),
              ),
              searchDecoration: InputDecoration(
                hintText: 'Type a country name',
                prefixIcon: const Icon(Icons.travel_explore),
                filled: true,
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12),
                ),
              ),
              textStyle: const TextStyle(
                color: Colors.indigo,
                fontWeight: FontWeight.w600,
              ),
              dialogTitleStyle: Theme.of(context)
                  .textTheme
                  .headlineSmall
                  ?.copyWith(fontWeight: FontWeight.bold),
              searchTextStyle: const TextStyle(fontSize: 16),
              itemTextStyle: const TextStyle(fontSize: 16),
              emptyResultTextStyle: const TextStyle(
                color: Colors.grey,
                fontStyle: FontStyle.italic,
              ),
              dialogShape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(20),
              ),
              dialogContentPadding: const EdgeInsets.fromLTRB(24, 12, 24, 24),
              itemPadding: const EdgeInsets.symmetric(horizontal: 8),
              showClearButton: true,
              items: _countries,
              searchMatcher: (item, query) =>
                  item.label.toLowerCase().contains(query.toLowerCase()) ||
                  item.value.toLowerCase().contains(query.toLowerCase()),
              validator: (value) =>
                  value == null ? 'Please select a country' : null,
              onChanged: (value) => setState(() => _country = value),
            ),
            const SizedBox(height: 24),
            CustomSearchableDropdown<String>(
              value: _remoteCountry,
              items: const [],
              hintText: 'Search remote countries',
              dialogTitle: 'Async bottom sheet',
              popupMode: DropdownPopupMode.bottomSheet,
              asyncItemsLoader: _loadCountries,
              searchDebounceDuration: const Duration(milliseconds: 300),
              showClearButton: true,
              decoration: const InputDecoration(
                labelText: 'Remote country',
                border: OutlineInputBorder(),
              ),
              onChanged: (value) => setState(() => _remoteCountry = value),
            ),
            const SizedBox(height: 24),
            FilledButton(
              onPressed: () => _formKey.currentState!.validate(),
              child: const Text('Submit'),
            ),
          ],
        ),
      ),
    );
  }
}
3
likes
160
points
205
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A customizable, searchable Flutter dropdown with form validation and generic value support.

Homepage

License

MIT (license)

Dependencies

flutter

More

Packages that depend on searchable_dropdown_form_field