🦋
Serverpod ~ Listで検索する
混乱の末に
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,
);
}
}
Discussion