🦋

Serverpod ~ Listで検索する

2023/08/28に公開

混乱の末に

Listでの検索に成功したので、記録しておく。
中間tableを使うとか、そういう話ではなく、
ただたんに、一つのtableの、一つのfieldを、複数のkeywordで絞る、だけ。

だけ、だけど悩みました。
Serverpodの情報少ない!

SearchPageのChipでkeywordsを選んでResultPageに送る

import 'package:acorn_client/acorn_client.dart';
import 'package:acorn_flutter/utils/button_format.dart';
import 'package:flutter/material.dart';
import 'package:serverpod_flutter/serverpod_flutter.dart';
import '../utils/chips_format.dart';
import 'result_page.dart';

var client = Client('http://localhost:8080/')
  ..connectivityMonitor = FlutterConnectivityMonitor();

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

  
  State<MultiSearchPage> createState() => _MultiSearchPageState();
}

class _MultiSearchPageState extends State<MultiSearchPage> {

  ///検索対象国の現在名
  List<Pays> listPays = [];
  List<Map<String, String>> displayListPays = [];
  final List<String> filtersPays = <String>[];
  final List<int> filtersPaysId = <int>[];

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Multiple Search Page'),
      ),
      body: Container(
            decoration: const BoxDecoration(
                image: DecorationImage(
                  image: AssetImage('assets/images/both.png'),
                  fit: BoxFit.cover,
                )
            ),
            child: Center(
              child: SingleChildScrollView(
                child: Column(
                  children: [
                    Padding(
                        padding: const EdgeInsets.all(20.0),
                      child: ButtonFormat(
                        onPressed: fetchPaysLookingFor,
                        label: 'Show and Select Current Countries',
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Wrap(
                        spacing: 5.0, // Gap between FilterChips
                        children: listPays.map((pays) {
                          return FilterFormat(
                            filteredKeys: filtersPays,
                            filteredValues: filtersPaysId,
                            filterKey: pays.pays,
                            filterValue: pays.id,
                          );
                        }).toList(),
                      ),
                    ),
                    ElevatedButton(
                      onPressed: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (context) => ResultPage(listPays: filtersPays),
                          ),
                        );
                        print ("$filtersPays");
                      },
                      child: const Text("Search"),
                    ),
                  ],
                ),
              ),
            ),
      ),
    );
  }

  
  void initState() {
    super.initState();
  }

  Future<void> fetchPaysLookingFor() async {
    try {
      listPays = await client.pays.getPays();
      setState(() {
        displayListPays = listPays.cast<Map<String, String>>();
      });
    } on Exception catch (e) {
      debugPrint('$e');
    }
  }
}

SearchByPaysModelで絞り込み

import 'package:flutter/material.dart';
import 'package:acorn_client/acorn_client.dart';
import 'package:serverpod_flutter/serverpod_flutter.dart';

class SearchByPaysModel extends ChangeNotifier {
  var client = Client('http://localhost:8080/')
    ..connectivityMonitor = FlutterConnectivityMonitor();

  ///国だけで絞る
  ///country name
  List<Principal> _principal = [];
  List<Principal> get principal => _principal;


  fetchPrincipal({List<String>? countries}) async {
    try {
      _principal = await client.principal.getPrincipal(keywords: countries);
      print("Getting principal with keywords: $countries");
      notifyListeners();
    } on Exception catch (e) {
      debugPrint('$e');
    }
  }
}

ResultPageに表示

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'search_model.dart';

class ResultPage extends StatelessWidget {
  //final String query;
  final List<String> listPays;
  //const ResultPage({super.key, required this.query});
  const ResultPage({super.key, required this.listPays});

  
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => SearchByPaysModel()..fetchPrincipal(countries: listPays),
      child: Scaffold(
        appBar: AppBar(
          title: Text('Search Results for: $listPays'),
        ),
        body: Consumer<SearchByPaysModel>(
          builder: (context, model, child) {
            return ListView.builder(
              itemCount: model.principal.length,
              itemBuilder: (context, index) {
                return Padding(
                  padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
                  child: Card(
                    color: const Color(0xFFe6e6fa),
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: ListTile(
                        leading: Text(model.principal[index].annee.toString()),
                        title: Text(model.principal[index].affair),
                        subtitle: Text(model.principal[index].pays),
                      ),
                    ),
                  ),
                );
              },
            );
          },
        ),
      ),
    );
  }
}

endpoint

import 'package:serverpod/serverpod.dart';
import '../generated/protocol.dart';

class PrincipalEndpoint extends Endpoint {
  //Principal

  Future<int> addPrincipal(Session session, Principal principal) async {
    await Principal.insert(session, principal);
    return principal.id!;
  }

  Future<List<Principal>> getPrincipal(Session session,
      {List<String>? keywords}) async {
    print("Getting principal with keywords: $keywords");

    var whereClause;
    if (keywords != null && keywords.isNotEmpty) {
      for (var keyword in keywords) {
        if (whereClause == null) {
          whereClause = Principal.t.pays.like('%$keyword%');
        } else {
          whereClause = whereClause | Principal.t.pays.like('%$keyword%');
        }
      }
    } else {
      whereClause = Constant(true);
    }

    return await Principal.find(
      session,
      where: (_) => whereClause,
      orderBy: Principal.t.annee,
    );
  }
}

先は長い

Flutter大学

Discussion