前提・問題点
現在、Flutter+Firebaseを利用してアプリ開発について学習を行っています。
その中でCloudFirestoreから持ってきたデータをDatatableに反映しているのですが、
Datatableのcheckbox
がlogをみるとselected
がタップ時はTrue
になっているので
反応はしているのですが、UI上でcheckbox
にチェックつかず困っています。
なので、選択してから削除ボタンを押すと該当のデータは削除されます。
しかし、UI上にチェックがついていないので選択されたかどうかがわからない状態にあります。
解決方法をご存知の方がいましたら回答いただけると助かります。
補足情報(FW/ツールのバージョンなど)
使用したもの
cloud_firestore: ^0.13.7
以下実装したコード
import 'dart:math';
import 'package:card_manager/add_deck_page.dart';
import 'package:card_manager/add_record_page.dart';
import 'package:card_manager/card_page.dart';
import 'package:card_manager/main.dart';
import 'package:card_manager/page_manager.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:provider/provider.dart';
import 'login_page.dart';
class RecordPage extends StatefulWidget {
final String email;
final String name;
BattleRecordPage(this.name, this.email);
@override
_RecordPage createState() => _RecordPage();
}
class _RecordPage extends State<RecordPage> {
List<DocumentSnapshot> selectedRecords;
List<DocumentSnapshot> documents;
@override
void initState() {
// TODO: implement initState
super.initState();
selectedRecords = [];
}
onSelectedRow(bool selected, DocumentSnapshot document) async {
setState(() {
if (selected) {
selectedRecords.add(record);
} else {
selectedRecords.remove(document);
}
});
}
deleteSelected() async {
setState(() {
if (selectedRecords.isNotEmpty) {
List<DocumentSnapshot> temp = [];
temp.addAll(selectedRecords);
for (DocumentSnapshot record in temp) {
Firestore.instance
.collection("Records")
.document(record.documentId)
.delete();
selectedRecords.remove(record);
}
}
});
}
Widget recordData(documents) =>
DataTable(
showCheckboxColumn: true,
columns: const <DataColumn>[
DataColumn(
label: Text(
"email",
style: TextStyle(fontStyle: FontStyle.italic),
),
numeric: false),
DataColumn(
label: Text(
"name",
style: TextStyle(fontStyle: FontStyle.italic),
),
numeric: false),
],
rows: documents
.map<DataRow>((document) =>
DataRow(
selected: selectedRecords.contains(document),
onSelectChanged: (b) {
onSelectedRow(b, document);
},
cells: <DataCell>[
DataCell(Text(document["email"]),
showEditIcon: false, placeholder: true),
DataCell(Text(document["name"]),
showEditIcon: false, placeholder: false),
]))
.toList());
@override
Widget build(BuildContext context) {
//ユーザ情報
final UserState userState = Provider.of<UserState>(context);
final FirebaseUser user = userState.user;
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Record"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () async {
Navigator.pushNamed(context, AddRecord.routeName,
arguments: AddRecord(widget.email, widget.name));
},
),
IconButton(
icon: Icon(Icons.delete),
onPressed: () async {
await deleteSelected();
},
)
],
),
body: Column(
children: <Widget>[
Expanded(
//非同期処理の結果をもとにWidget作成
child: StreamBuilder<QuerySnapshot>(
//非同期処理結果→future
stream: Firestore.instance
.collection("Records")
.where("uid", isEqualTo: user.uid)
.where("name", isEqualTo: widget.name)
.orderBy("date")
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
documents =
snapshot.data.documents;
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: FittedBox(child: recordData(documents)));
}
return Center(
child: Text("読み込み中..."),
);
}),
)
],
),
);
}
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
以下のように、ドキュメントのid
で比較するようにしてみてください。
※ FireStoreのバージョンが古い場合はdocumentID
という名前かもしれません。
DataRow(
selected: selectedRecords.any((record) => record.id == document.id),
onSelectChanged: ...
cells: ...
あと、以下の部分のrecord
という変数はdocument
の間違いでは無いでしょうか?
onSelectedRow(bool selected, DocumentSnapshot document) async {
setState(() {
if (selected) {
selectedRecords.add(record);
} else {
selectedRecords.remove(document);
}
});
}
追記(09/02/21:00): チェックが外れない問題の修正方法
配列から削除するのにremove
を使うと、DocumentSnapshot
の場合、同じインスタンスかどうかで判定されてしまいます。
代わりにremoveWhere
を使ってid
を比較して同じものを削除するようにしてみてください。
onSelectedRow(bool selected, DocumentSnapshot document) async {
setState(() {
if (selected) {
selectedRecords.add(document);
} else {
selectedRecords.removeWhere((record) => record.id == document.id);
}
});
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.34%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2020/09/02 20:52 編集
該当箇所について修正したところ、checkboxにチェック自体はつくようになりましたが
チェックが外れないという問題が発生するようになりました。
何か解決方法がありましたらご教授いただけると助かります。
(selectedやsellectchangedの結果自体はtrueとfalseが正しく返されていました)
※recordの部分はdocumentの間違いです。
2020/09/02 21:08
2020/09/02 22:25 編集
自分が無知なもので少しお聞きしたいのですが、
checkが入る場合と入らない場合のどちらに関しても
DocumentSnapshotだとインスタンスで判断すると
結果がfalseと帰ってきてcheckが正常に動作しないのは何故でしょうか?
お手数おかけしますが回答いただけると幸いです。
2020/09/02 23:30
同じ値を持っていますが、別物なので結果がfalseになってしまっていたのだと思います。
2020/09/02 23:46