Dolphin
Dolphin

Reputation: 38641

how to trigger search automatically when using SearchDelegate buildSuggestions in flutter

Now I am using SearchDelegate in flutter 2.0.1, this is my buildSuggestions code:

@override
  Widget buildSuggestions(BuildContext context) {
    var channelRequest = new ChannelRequest(pageNum: 1, pageSize: 10, name: query);
    if (query.isEmpty) {
      return Container();
    }

    return FutureBuilder(
        future: ChannelAction.fetchSuggestion(channelRequest),
        builder: (context, AsyncSnapshot snapshot) {
          if (snapshot.hasData) {
            List<ChannelSuggestion> suggestions = snapshot.data;
            return buildSuggestionComponent(suggestions, context);
          } else {
            return Text("");
          }
        });
  }


 Widget buildSuggestionComponent(List<ChannelSuggestion> suggestions, BuildContext context) {
    return ListView.builder(
      itemCount: suggestions.length,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text('${suggestions[index].name}'),
          onTap: () async {
            query = '${suggestions[index].name}';
            
          },
        );
      },
    );
  }

when select the recommand text, I want to automatically trigger search event(when I click the suggestion text, trigger the search, fetch data from server side and render the result to UI) so I do not need to click search button. this is my search code:

@override
  Widget buildResults(BuildContext context) {
    var channelRequest = new ChannelRequest(pageNum: 1, pageSize: 10, name: query);
    return buildResultImpl(channelRequest);
  }

  Widget buildResultImpl(ChannelRequest channelRequest) {
    return FutureBuilder(
        future: ChannelAction.searchChannel(channelRequest),
        builder: (context, AsyncSnapshot snapshot) {
          if (snapshot.hasData) {
            List<Channel> channels = snapshot.data;
            return buildResultsComponent(channels, context);
          } else {
            return Text("");
          }
          return Center(child: CircularProgressIndicator());
        });
  }

what should I do to implement it? I have tried invoke buildResults function in buildSuggestionComponent but it seems not work.

Upvotes: 0

Views: 2925

Answers (2)

RIX
RIX

Reputation: 133

I have done it through a simple workaround

Simply add this line after your database call

query = query

But be careful of the call looping

Upvotes: -1

Bach
Bach

Reputation: 3326

To update the data based on the query, you can make an API call to get the result when clicking on a suggestion, then use a StreamController to stream the results to the buildResults() method and call showResults().

I'm creating a simple app here for demonstration:

import 'dart:async';

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(home: Home()));
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final _controller = StreamController.broadcast();

  @override
  dispose() {
    super.dispose();
    _controller.close();
  }

  Future<void> _showSearch() async {
    await showSearch(
      context: context,
      delegate: TheSearch(context: context, controller: _controller),
      query: "any query",
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Search Demo"),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.search),
            onPressed: _showSearch,
          ),
        ],
      ),
    );
  }
}

class TheSearch extends SearchDelegate<String> {
  TheSearch({this.context, this.controller});

  BuildContext context;
  StreamController controller;
  final suggestions =
      List<String>.generate(10, (index) => 'Suggestion ${index + 1}');

  @override
  List<Widget> buildActions(BuildContext context) {
    return [IconButton(icon: Icon(Icons.clear), onPressed: () => query = "")];
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
      icon: AnimatedIcon(
        icon: AnimatedIcons.menu_arrow,
        progress: transitionAnimation,
      ),
      onPressed: () {
        close(context, null);
      },
    );
  }

  @override
  Widget buildResults(BuildContext context) {
    return StreamBuilder(
      stream: controller.stream,
      builder: (context, snapshot) {
        if (!snapshot.hasData)
          return Container(
              child: Center(
            child: Text('Empty result'),
          ));
        return Column(
          children: List<Widget>.generate(
            snapshot.data.length,
            (index) => ListTile(
              onTap: () => close(context, snapshot.data[index]),
              title: Text(snapshot.data[index]),
            ),
          ),
        );
      },
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    final _suggestions = query.isEmpty ? suggestions : [];
    return ListView.builder(
      itemCount: _suggestions.length,
      itemBuilder: (content, index) => ListTile(
          onTap: () {
            query = _suggestions[index];
            // Make your API call to get the result
            // Here I'm using a sample result
            controller.add(sampleResult);
            showResults(context);
          },
          title: Text(_suggestions[index])),
    );
  }
}

final List<String> sampleResult =
    List<String>.generate(10, (index) => 'Result ${index + 1}');

Upvotes: 1

Related Questions