Flutter correctly print map having a future map - flutter

someone can help with this code?
I must print a query result inside the dropdown as List
The error flutter give me back is:
The following NoSuchMethodError was thrown building
DropDownFormField(dirty, dependencies: [_FormScope], state:
FormFieldState#e264a): Class 'Future<List>' has no
instance method '[]'. Receiver: Instance of 'Future<List>'
Tried calling: The relevant error-causing widget was:
DropDownFormField
I've tryed getAllBrockers and getAllBrockers2 way
class _AutomationAddScreen extends State<AutomationAdd> {
DataRepository _repository;
final _formKey = GlobalKey<FormState>();
String _broN = "";
Future<Map> _broMap;
Future<List> _bro;
static Future<List> getAllBrockers2(Future<List<Brockers>> l) async {
List q;
List<Brockers> b = await l;
for (var i = 0; i < b.length; i++) {
q.add(DataList(b[i].name, b[i].id));
}
return q;
}
static Future<Map> getAllBrockers(Future<List<Brockers>> l) async {
Map hBro;
Map m;
List<Brockers> b = await l;
for (var i = 0; i < b.length; i++) {
m = {"display": b[i].name, "value": b[i].id};
hBro.addAll(m);
}
return hBro;
}
#override
void initState() {
super.initState();
_repository = SqlRepository();
//_broMap = getAllBrockers(_repository.getAllBrockers());
_bro = getAllBrockers2(_repository.getAllBrockers());
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Form(
key: _formKey,
child: ListView(
children: <Widget>[
//SELECT BROCKER
Padding(
padding: EdgeInsets.only(top: 16),
child: DropDownFormField(
titleText: 'Connessione',
hintText: 'Selezionane uno',
value: _broN,
//dataSource: [_broMap],
dataSource: [_bro],
textField: 'display',
valueField: 'value',
onChanged: (display) {
setState(() {
_broN = display.toString();
});
},
),
),
],
),
),
));
}
}
class DataList {
String display;
int value;
DataList(this.display, this.value);
#override
String toString() {
return '{ ${this.display}, ${this.value} }';
}
}

Instead of using Future<List> or Future<Map>, you should use List or Map. The error specifically mentions that it cannot call [] on Future<List>.
The DropdownFormField is unable to create its list of items because you have provided a Future.
You can try using the following approach -
class _AutomationAddScreen extends State<AutomationAdd> {
DataRepository _repository;
final _formKey = GlobalKey<FormState>();
String _broN = "";
Map _broMap; // New
List _bro = List<DataList>(); // New
static Future<void> getAllBrockers2() async { // New
final b = await _repository.getAllBrockers(); // New
for (var i = 0; i < b.length; i++) {
_bro.add(DataList(b[i].name, b[i].id)); // New
}
setState(() {}); // New
}
static Future<Map> getAllBrockers(Future<List<Brockers>> l) async {
Map hBro = {}; // New
Map m;
List<Brockers> b = await l;
for (var i = 0; i < b.length; i++) {
m = {"display": b[i].name, "value": b[i].id};
hBro.addAll(m);
}
return hBro;
}
#override
void initState() {
super.initState();
_repository = SqlRepository();
//_broMap = getAllBrockers(_repository.getAllBrockers());
getAllBrockers2(); // New
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Form(
key: _formKey,
child: ListView(
children: <Widget>[
//SELECT BROCKER
Padding(
padding: EdgeInsets.only(top: 16),
child: DropDownFormField(
titleText: 'Connessione',
hintText: 'Selezionane uno',
value: _broN,
//dataSource: [_broMap],
dataSource: [_bro],
textField: 'display',
valueField: 'value',
onChanged: (display) {
setState(() {
_broN = display.toString();
});
},
),
),
],
),
),
));
}
}
class DataList {
String display;
int value;
DataList(this.display, this.value);
#override
String toString() {
return '{ ${this.display}, ${this.value} }';
}
}

Related

Multiple showDialog for validation

On my project I need to use several showDialog one after the other.
For user creation, I use a SearchField widget to retrieve info from a table related to the user.
If the SearchField value does not exist I would like to propose the creation. Depending on the choice either the form is in error or I propose to register the user.
For this I use a showDialog in the validator of the SearchField and an if validator is correct.
My problem is that my second dialog box is displayed before validating the first one and even above that of the SearchField.
What is the correct way to do this?
Thank you,
class InformationsPage extends StatefulWidget {
const InformationsPage({
required Key key,
required this.user,
required this.type,
}) : super(key: key);
final User user;
final FenType type;
#override
InformationsPageState createState() => InformationsPageState();
}
class InformationsPageState extends State<InformationsPage>
with AutomaticKeepAliveClientMixin {
InformationsPageState({this.user});
final User? user;
late UserApi _api;
#override
bool get wantKeepAlive => true;
bool _familyIsCreated = false;
late User userSaved;
late FenType type;
//Info Form
var _pseudoController = TextEditingController();
var _familyController = TextEditingController();
#override
void initState() {
super.initState();
_api = UserApi();
_pseudoController = TextEditingController(text: widget.user.pseudo);
_familyController = TextEditingController(text: widget.user.familyName);
userSaved = User.fromUser();
type = widget.type;
}
#override
void dispose() {
_pseudoController.dispose();
_familyController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
super.build(context);
return Column(
children: <Widget>[
FutureBuilder(
future: _api.getFamilies(),
builder: (context, AsyncSnapshot<List<Family>> snapshot) {
if (snapshot.hasError) {
return Center(
child: Text(
"Something wrong with message: ${snapshot.error.toString()}"));
} else if (snapshot.connectionState == ConnectionState.done) {
List<Family> _list = snapshot.data!;
return _buildDropdownSearchFamilies(_list);
} else {
return const Center(child: CircularProgressIndicator());
}
}),
TextFormField(
readOnly: type == FenType.read ? true : false,
inputFormatters: [LowerCaseTextFormatter()],
controller: _pseudoController,
onSaved: (value) => userSaved.pseudo = value,
decoration: const InputDecoration(
icon: Icon(Icons.person),
hintText: 'Pseudo',
labelText: 'Pseudo',
),
validator: (value) =>
value!.isEmpty ? 'Obligatory' : null),
],
);
}
int? _contains(List<Family> list, String? name) {
int? res = -1;
for (Family element in list) {
if (element.name == name) {
res = element.id;
break;
}
}
return res;
}
Widget _buildDropdownSearchFamilies(List<Family> _list) {
return SearchField(
controller: _familyController,
suggestions: _list
.map((e) =>
SearchFieldListItem(e.name!, child: Text(e.name!), item: e.id))
.toList(),
hint: 'Family',
validator: (x) {
if (x!.isEmpty) {
userSaved.familyId = null;
userSaved.familyName = null;
return null;
}
int? id = _contains(_list, x);
if (id == -1) {
userSaved.familyId == null;
showDiaglog(x);
if (userSaved.familyId != null) {
return null;
} else {
return 'Family not exist';
}
} else {
userSaved.familyId = id;
userSaved.familyName = x;
return null;
}
},
searchInputDecoration: const InputDecoration(
labelText: 'Family', icon: Icon(Icons.groups)),
itemHeight: 50,
onTap: (x) {
userSaved.familyId = x.item as int?;
userSaved.familyName = x.child.toString();
});
}
showDiaglog(String family) async {
String title = "Family";
String message =
"Family $family not exist. Create ?";
String textKoButton = "no";
String textOkButton = "yes";
MyDialog alert = MyDialog(
title: title,
message: message,
onPressedKo: koButtonPressed(),
onPressedOk: okButtonPressed(family),
textKoButton: textKoButton,
textOkButton: textOkButton);
await showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
void Function() koButtonPressed() => () {
_familyIsCreated = false;
Navigator.of(context).pop(false);
};
void Function() okButtonPressed(family) => () {
_save(family);
Navigator.of(context).pop();
};
void _save(family) async {
UserApi apiUser = UserApi();
Family oldF = Family.empty();
Family newF = Family.empty();
newF.name = family;
newF.createdAt = oldF.createdAt;
newF.deletedAt = newF.deletedAt;
Map<String, dynamic> data = oldF.toJson(newF);
int res = -1;
res = await apiUser.createFamily(data);
SnackBar snackBar;
if (res != -1) {
snackBar = MyWidget.okSnackBar('Family created');
userSaved.familyId = res;
userSaved.familyName = family;
} else {
snackBar = MyWidget.koSnackBar(
'Family not created');
userSaved.familyId = null;
userSaved.familyName = null;
}
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
My form :
class UserFormPage extends StatefulWidget {
static const String routeName = '/admin/user-form';
final User? user;
final FenType fenType;
const UserFormPage({Key? key, required this.user, required this.fenType})
: super(key: key);
#override
_UserFormPageState createState() => _UserFormPageState();
}
class _UserFormPageState extends State<UserFormPage>
with SingleTickerProviderStateMixin {
static final GlobalKey<FormState> _formKey =
GlobalKey<FormState>(debugLabel: '_appState');
static final GlobalKey<InformationsPageState> _infoKey =
GlobalKey<InformationsPageState>();
late TabController _controller;
late User _user;
late User _userSaved;
#override
void initState() {
super.initState();
_controller = TabController(vsync: this, length: 2);
_user = widget.user!;
_userSaved = widget.user!;
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () =>
Navigator.pushReplacementNamed(context, Routes.admUserList),
),
title: const Text('Member'),
actions: <Widget>[
Visibility(
visible: widget.fenType != FenType.read ? true : false,
child: IconButton(
icon: const Icon(Icons.save),
onPressed: () {
if (!_formKey.currentState!.validate()) {
return;
}
showDiaglog();
},
))
],
bottom: TabBar(
controller: _controller,
tabs: const [
Tab(text: 'Info'),
Tab(text: 'Others'),
],
),
),
body: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Flexible(
child: TabBarView(
controller: _controller,
children: <Widget>[
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InformationsPage(
user: _user,
key: _infoKey,
type: widget.fenType),
])),
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DetailsPage(
user: _user,
key: _detailsKey,
type: widget.fenType)
],
)),
],
))
],
))),
);
}
void _save() async {
final infoState = _infoKey.currentState;
_userSaved = infoState?.userSaved ?? _user;
_userSaved.pseudo = infoState?.userSaved.pseudo ?? _user.pseudo;
Map<String, dynamic> data = _user.userToJsonClean(_userSaved);
if (!_userSaved.userIsUpdated()) {
final outSnackBar = MyWidget.okSnackBar('Not update');
ScaffoldMessenger.of(context).showSnackBar(outSnackBar);
} else {
UserApi apiUser = UserApi();
bool res = false;
res = widget.fenType == FenType.update
? await apiUser.update(data)
: await apiUser.create(data);
SnackBar snackBar;
res
? snackBar = MyWidget.okSnackBar('Member saved')
: snackBar = MyWidget.koSnackBar(
'Member not saved');
ScaffoldMessenger.of(context).showSnackBar(snackBar);
_user = _userSaved;
if (widget.fenType == FenType.create) {
Navigator.of(context).popAndPushNamed(Routes.admUserList);
}
}
}
void showDiaglog() {
String pseudo = _userSaved.pseudo!;
String title = "Save";
String message = widget.fenType == FenType.create
? "Create member $pseudo ?"
: "Save meber $pseudo ?";
String textKoButton = "no";
String textOkButton = "yes";
MyDialog alert = MyDialog(
title: title,
message: message,
onPressedKo: koButtonPressed(),
onPressedOk: okButtonPressed(),
textKoButton: textKoButton,
textOkButton: textOkButton);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
void Function() koButtonPressed() => () {
Navigator.of(context).pop(false);
};
void Function() okButtonPressed() => () {
_formKey.currentState!.save();
_save();
Navigator.of(context).pop();
};
}
I resolve this problem to modified the widget SearchField to a DropdownSearch.

Flutter: ListView not displaying anything + lazy loading

I am new in flutter and trying to create a listview with load more functionality.
Here is my class. It is not displaying anything, blank screen. List has data I am getting result in console.
class ReportPurchaseNew extends StatefulWidget {
final AdminUserDetails userDetails;
final String title;
const ReportPurchaseNew({Key key, this.title, this.userDetails})
: super(key: key);
#override
State<StatefulWidget> createState() => new ReportPurchaseState();
}
class ReportPurchaseState extends State<ReportPurchaseNew> {
String fromDate = "", toDate = "", usageType = "";
int limit = 7, offset = 0;
static int page = 0;
List<Result> _List = new List();
List<Result> _filteredList;
Future<PurchaseReport> _PurchaseReportResponse;
List<UsageResult> _usageList = [];
UsageResult _usageVal;
ScrollController _sc = new ScrollController();
bool isLoading = false;
//List users = new List();
#override
void initState() {
this._getMorePurchase(page);
super.initState();
_sc.addListener(() {
if (_sc.position.pixels ==
_sc.position.maxScrollExtent) {
_getMorePurchase(page);
}
});
}
#override
void dispose() {
_sc.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Lazy Load Large List"),
),
body: Container(
child: _buildList(),
),
resizeToAvoidBottomInset: false,
);
}
Widget _buildList() {
return ListView.builder(
itemCount: _List.length + 1, // Add one more item for progress indicator
padding: EdgeInsets.symmetric(vertical: 8.0),
itemBuilder: (BuildContext context, int index) {
if (index == _List.length) {
return _buildProgressIndicator();
} else {
return new ListTile(
leading: CircleAvatar(
radius: 30.0,
),
title :Text("my:"+(_List[index]
.product)),
subtitle: Text((_List[index]
.unitPrice)),
);
}
},
controller: _sc,
);
}
Widget _buildProgressIndicator() {
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new Opacity(
opacity: isLoading ? 1.0 : 00,
child: new CircularProgressIndicator(),
),
),
);
}
Future<PurchaseReport> getProjectDetails() async {
var result = await PurchaseReportRequest(
context,
widget.userDetails.result.raLoginId,
limit.toString(),
offset.toString(),
fromDate,
toDate,
_usageVal!=null ? _usageVal.name : "" ,
);
return result;
}
void _getMorePurchase(int index) async {
if (!isLoading) {
setState(() {
isLoading = true;
});
_PurchaseReportResponse = getProjectDetails();
setState(() {
isLoading = false;
_PurchaseReportResponse.then((response) {
if (response != null) {
_List.addAll(response.result);
page = page + limit;
print("printing length : "
+_List.length.toString());
for (int i = 0; i < response.result.length; i++) {
print('name:' +_List[i].product );
}
} else {
errorRaisedToast(context);
}
});
});
}
}
}
Try This,
if (response != null) {
List newList = new List();
// _List.addAll(response.result);
page = page + limit;
print("printing length : "
+_List.length.toString());
for (int i = 0; i < response.result.length; i++) {
newList.add(response.result[i]);
print('name:' +_List[i].product);
}
isLoading = false;
_List.addAll(newList);
page++;
} else {
errorRaisedToast(context);
}

Flutter list, chips and MultiSelect

I am trying to transfer the result of a query to a list but it is not working properly.
Below you will find the source code, it will be more clear.
I'm getting this error "type 'List' is not a subtype of type 'List'"
if the error is clear, I do not understand how to fix that.
I would like to get _allResults (contextName) into the list _context.
Many thanks for your help.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:gtd_official_sharped_focused/models/context.dart';
import 'package:multi_select_flutter/multi_select_flutter.dart';
String taskImportant;
String taskUrgent;
class EngagePage_Sept_2021 extends StatefulWidget {
EngagePage_Sept_2021({Key key, }):super(key:key);//this.title}) : super(key: key);
// final String title;
#override
_EngagePage_Sept_2021State createState() => _EngagePage_Sept_2021State();
}
class _EngagePage_Sept_2021State extends State<EngagePage_Sept_2021> {
TextEditingController _searchController = TextEditingController();
Future resultsLoaded;
List _allResults = [];
List _resultsList = [];
#override
void initState() {
super.initState();
_selectedContext = _allResults;//_context;
_searchController.addListener(_onSearchChanged);
}
#override
void dispose(){
_searchController.removeListener(_onSearchChanged);
_searchController.dispose();
super.dispose();
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
resultsLoaded = getUsersListOfTasksStreamSnapshots();
}
_onSearchChanged() {
searchResultsList();
}
/*static List<Contexts> _monTest = [
Contexts(contextName: ),
];
*/
static List<Contexts> _context = [. //Here, I would prefer to store the data.docs
Contexts(id: '1', contextName: "name 1"),
Contexts(id: '2', contextName: "name 2"),
Contexts(id: '3', contextName: "name 3"),
];
// static List<Contexts> _test = _allResults;
final _itemsContext = _context
.map((context) => MultiSelectItem<Contexts>(context, context.contextName))
.toList();
List<Contexts> _selectedContext = [];
final _multiSelectKeyContext = GlobalKey<FormFieldState>();
final _multiSelectKeyStatus = GlobalKey<FormFieldState>();
final _multiSelectKey4 = GlobalKey<FormFieldState>();
final _multiSelectKeyTime = GlobalKey<FormFieldState>();
searchResultsList() {
var showResults = [];
if(_searchController.text != "") {
for(var taskSnapshot in _allResults){
var title = Contexts.fromSnapshot(taskSnapshot).contextName.toLowerCase();
if(title.contains(_searchController.text.toLowerCase())) {
showResults.add(taskSnapshot);
}
}
} else {
showResults = List.from(_allResults);
}
setState(() {
_resultsList = showResults;
});
}
getUsersListOfTasksStreamSnapshots() async {
var data = await FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('contexts')
.get();
setState(() {
_allResults = data.docs;
print(_allResults);
});
searchResultsList();
return 'complete';
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('TEST CHIP'),
),
drawer: MyMenu(),
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.all(20),
child: Column(
children: <Widget>[
//################################################################################################
// CONTEXT - MultiSelectBottomSheetField with validators
//################################################################################################
MultiSelectBottomSheetField<Contexts>(
key: _multiSelectKeyContext,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: Text("Context"),
buttonText: Text("Context",style: TextStyle(fontSize: 18),),
items: _itemsContext,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "";
}
List<String> names = values.map((e) => e.contextName).toList();
return null;
},
onConfirm: (values) {
setState(() {
_selectedContext = values;
});
_multiSelectKeyContext.currentState.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedContext.remove(item);
});
_multiSelectKeyContext.currentState.validate();
},
),
),
SizedBox(height: 40),
//################################################################################################
// STATUS - MultiSelectBottomSheetField with validators
//################################################################################################
],
),
],
),
),
),
);
}
}
Model context
import 'package:cloud_firestore/cloud_firestore.dart';
class Contexts {
String id;
String contextName;
Contexts({
this.id,
this.contextName,
});
// formatting for upload to Firebase when creating the trip
Map<String, dynamic> toJson() =>
{
'context_Name': contextName,
};
//creating a Task object from a firebase snapshot
Contexts.fromSnapshot(DocumentSnapshot snapshot) :
id = snapshot.id,
contextName = snapshot['context_Name'];
}

List view not getting rebuild properly

I have this comment section in my application.
User can like a comment.
Whenever a comment is added, I call the database to get the latest comment and rebuild the class.
But as shown below When a new comment is added, it retains the state of the previous comment
as seen above when a not liked comment is added it is having state of previous comment
Below is the given code
#override
void initState() {
getComments();
super.initState();
}
getComments() async {
try {
List<Comment> commentList =
await Provider.of<Database>(context, listen: false)
.postComments(widget.postid);
setState(() {
data = commentList;
});
} catch (e) {
setState(() {
data = 'error';
});
// throw ('e');
}
}
dynamic data;
addComment(BuildContext context) async {
String commentData = _textEditingController.text.trim();
if (commentData.isNotEmpty) {
setState(() {
showShimmer = true;
_textEditingController.clear();
});
bool result = await Provider.of<Database>(context, listen: false)
.addMessageToPost(widget.postid, true, commentData);
if (result) {
getComments();
}
}
}
final TextEditingController _textEditingController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: settingsAppBar(context, 'Comments'),
body: Column(
children: [
showShimmer
? Shimmer.fromColors(
baseColor: Colors.grey[200]!,
highlightColor: Colors.grey[100]!,
child: ShimmerWidget())
: Container(),
Expanded(
child: data == null
? Center(child: CircularProgressIndicator())
: data == 'error'
? Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextButton(
onPressed: () {
getComments();
},
child: Text('Retry')),
],
),
)
: data.length >= 1
? RefreshIndicator(
onRefresh: () async {
setState(() {
data = null;
});
getComments();
},
child: ListView(
controller: _scrollController,
children: buidlCommentWidgets()),
)
: Text('No data'),
),
SafeArea(...textfield) ],
),
),
],
),
),
],
),
);
}
List<Widget> buidlCommentWidgets() {
List<Widget> commentWidgetList = [];
for (var i = 0; i < data.length; i++) {
commentWidgetList.add(Padding(
padding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 8.0),
child: CommentListTile(
comment: data[i],
postUid: widget.postedUid,
),
));
}
return commentWidgetList;
}
}
//////////////////////////////////////////////////////////////
class CommentListTile extends StatefulWidget {
const CommentListTile({
Key? key,
required this.comment,
required this.postUid,
this.isReply = false,
}) : super(key: key);
final Comment comment;
final String postUid;
final bool isReply;
#override
_CommentListTileState createState() => _CommentListTileState();
}
class _CommentListTileState extends State<CommentListTile> {
late bool isLiked;
late int likeCount;
handleLike(BuildContext context) async {
setState(() {
isLiked = !isLiked;
likeCount = isLiked ? likeCount + 1 : likeCount - 1;
});
bool result = await Provider.of<Database>(context, listen: false)
.postActivity(
PostActivityEnum.likeDislikeComment, widget.comment.commentId);
if (!result) {
setState(() {
isLiked = !isLiked;
likeCount = isLiked ? likeCount + 1 : likeCount - 1;
});
}
}
#override
void initState() {
isLiked = widget.comment.isLikedByViewer;
likeCount = widget.comment.likesCount;
super.initState();
}
#override
Widget build(BuildContext context) {
....ListTile
This is a very common problem in the flutter.
This happens due to the widget tree and the render tree difference, Identification of the widget by its own Key can be easier for the flutter to keep an update on both render and widget tree.
For an easy solution, you can pass a unique key to the CommentListTile widget while building the list and also while adding a new widget to the list.
List<Widget> buidlCommentWidgets() {
List<Widget> commentWidgetList = [];
for (var i = 0; i < data.length; i++) {
commentWidgetList.add(Padding(
padding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 8.0),
child: CommentListTile(
key: SOME_UNIQUE_KEY_HERE // Add Unique key here
comment: data[i],
postUid: widget.postedUid,
),
));
}
return commentWidgetList;
}
It can be easy if you have some kind of commentId.
EDIT: 27 Aug 2021
You definitely should use your buildCommentWidgets() method like this:
List<Widget> buidlCommentWidgets() {
return data.map((comment) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: CommentListTile(
key: SOME_UNIQUE_KEY_HERE // Add Unique key here
comment: comment,
postUid: widget.postedUid,
),
);
}).toList();
}

How I can call setState() of class A from Class B

when I click on IconButton() to delete All items from the list movies I can't see that change until I reopen the page again...
anyone know how I could fix
this my infoPage(("class B")):
class InfoPage extends StatefulWidget {
int id;
int pageId;
InfoPage(this.id,this.pageId);
#override
_InfoPageState createState() => _InfoPageState(id,pageId);
}
class _InfoPageState extends State<InfoPage> {
var db = DatabaseHelper();
String title = "";
String about = "";
String rate = "";
String date = "";
int id;
int pageId;
_InfoPageState(this.id,this.pageId);
#override
void initState() {
super.initState();
if(pageId == 1){
_getMovie();
}
}
void _getMovie() async {
Movie thisMovie = await db.getMovie(id);
setState(() {
title = thisMovie.name;
about = thisMovie.description;
rate = thisMovie.rate;
date = thisMovie.date;
});
}
_deleteMovie() async{
await db.deleteMovie(id);
Navigator.pop(context);
setState(() {
CardsListViewState(pageId).deleteAllList();
});
}
#override
Widget build(BuildContext context) {
Navigator.canPop(context);
return Scaffold(
body: Container(
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 10),
child:Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: Container(),
),
Container(
margin: EdgeInsets.only(right: 10),
child: IconButton(
icon: Icon(Icons.delete,color: Color(0xffFC4D4D),),
onPressed: (){
_deleteMovie();
}
)
)
],
),
)
],
),
),
);
}
}
and this my CardsListView(("class A"))
class CardsListView extends StatefulWidget {
int whereComeFrom;
CardsListView(this.whereComeFrom);
#override
CardsListViewState createState() => CardsListViewState(whereComeFrom);
}
class CardsListViewState extends State<CardsListView> {
int whereComeFrom;
CardsListViewState(this.whereComeFrom);
var db = DatabaseHelper();
List mainList = [];
final List<Movie> movies = <Movie>[];
deleteAllList() async{
await db.deleteMovies();
setState(() {
movies.clear();
});
}
#override
void initState() {
super.initState();
_readUnites();
if(whereComeFrom == 1){
mainList = movies;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body:
GridView.count(
crossAxisCount: 3,
addAutomaticKeepAlives: true,
childAspectRatio: (1/1.5),
children: List.generate(mainList.length, (index){
return CardUnite(mainList[index].name,mainList[index].id,whereComeFrom);
})
),
);
}
You can use a callback function from the parent class supplied to the child class.
Remember that functions are first class objects in Dart.
Just pass in a function that calls setState to the child and have the child call that function.