error: The argument type 'Null' can't be assigned to the parameter type 'Map<String, dynamic>' - flutter

I am writing my first Flutter App with some online tutorials and I found error that I can't fix it.
I am trying to add Navigation by Navigator, but I can't understand why it doesn't work.
Once I am using Navigator in GestureDetector and it works fine, but I don't know what I supposed to do in floatingActionButton to make it work the same way. Note(NoteMode.Adding, null) probably should be something else instead null, because this null is making error (error from title). Can someone explain me what I am doing wrong and what I don't undarstand
Note List
#override
_NoteListState createState(){return _NoteListState();}
}
class _NoteListState extends State<NoteList> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Notes"),
),
body: FutureBuilder(
future: NoteProvider.getNoteList(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
final notes = snapshot.data;
return ListView.builder(
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) =>
Note(NoteMode.Editing, (notes as dynamic)[index]))
);
},
child: Card(
child: Padding(
padding: const EdgeInsets.only(
top: 30.0, bottom: 30.0, left: 13, right: 22),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_NoteTitle((notes as dynamic)[index]['title']),
Container(height: 3,),
_NoteText((notes as dynamic)[index]['text']),
],
),
),
),
);
},
itemCount: notes.length,
);
}
return Center(child: CircularProgressIndicator());
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => Note(NoteMode.Adding, null)));
},
child: Icon(Icons.add),
),
);
}
}
Note
enum NoteMode{
Editing,
Adding
}
class Note extends StatefulWidget{
final NoteMode noteMode;
final Map<String, dynamic> note;
Note(this.noteMode, this.note,);
#override
State<Note> createState() => _NoteState();
}
class _NoteState extends State<Note> {
final TextEditingController _titleController = TextEditingController();
final TextEditingController _textController = TextEditingController();
List<Map<String, String>> get _notes => NoteInheritedWidget.of(context).notes;
#override
void didChangeDependencies(){
if(widget.noteMode == NoteMode.Editing){
_titleController.text = widget.note['title'];
_textController.text = widget.note['text'];
}
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
widget.noteMode == NoteMode.Adding ? 'Add note' : 'Edit note',
),
),
body: Padding(
padding: const EdgeInsets.all(40.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
controller: _titleController,
decoration: InputDecoration(
hintText: "Note title",
),
),
Container(height: 8,),
TextField(
controller: _textController,
decoration: InputDecoration(
hintText: "Note text",
),
),
Container(height: 15,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_NoteButton('SAVE', Colors.lightBlue, (){
final title = _titleController.text;
final text = _textController.text;
if(widget.noteMode == NoteMode.Adding){
NoteProvider.insertNote({
'title': title,
'text': text
});
} else if (widget.noteMode == NoteMode.Editing){
NoteProvider.updateNote( {
'id': widget.note['id'],
'title': _titleController.text,
'text': _textController.text,
});
}
Navigator.pop(context);}),
_NoteButton('DISCARD', Colors.grey, (){Navigator.pop(context);}),
widget.noteMode == NoteMode.Editing ?
_NoteButton('DELETE', Colors.redAccent, () async {
await NoteProvider.deleteNote(widget.note['id']);
Navigator.pop(context);})
: Container(),
],
)
],
),
),
);
}
}

Either you have to pass Map in place of null because you are receiving a Map on that page
Navigator.push(context, MaterialPageRoute(builder: (context) => Note(NoteMode.Adding, {"key":"value"})));
or you have to make Map nullable as
class Note extends StatefulWidget{
final NoteMode noteMode;
final Map<String, dynamic>? note;
Note(this.noteMode, this.note,);
#override
State<Note> createState() => _NoteState();
}

Related

How to convert from Map<String, dynamic> to List<String> in flutter

I'm trying to make multiple select widgets and the data from firebase database
CollectionReference submission = FirebaseFirestore.instance.collection('cuti'); is data with type Map<String, dynamic> while on dataSource: must be type List<object?>
this is the full code
class multiple extends StatefulWidget {
const multiple({super.key});
#override
State<multiple> createState() => _multipleState();
}
class _multipleState extends State<multiple> {
late MultiselectController _multiselectController;
late Random random;
late List<String> _items;
CollectionReference submission = FirebaseFirestore.instance.collection('cuti');
#override
void initState() {
super.initState();
_multiselectController = MultiselectController();
_items = List.generate(10, (index) => '$submission'); // in submission Type: Map<String, dynamic>
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('List'),
),
body: MultiselectScope(
controller: _multiselectController,
dataSource: _items, // in here must be Type: List<String>
clearSelectionOnPop: true,
keepSelectedItemsBetweenUpdates: true,
// initialSelectedIndexes: [1, 3],
onSelectionChanged: (selectedIndexes, selectedItems) {},
child: Padding(
padding: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: ListView.builder(
itemCount: _items.length,
itemBuilder: (context, index) {
final controller = MultiselectScope.controllerOf(context);
final itemSelected = controller.isSelected(index);
return InkWell(
onLongPress: () {
if (!controller.selectionAttached) {
controller.select(index);
}
},
onTap: () {
print('item is selected $itemSelected');
if (controller.selectionAttached) {
controller.select(index);
}
},
child: Padding(
padding: EdgeInsets.all(10),
child: Container(
color: itemSelected
? Theme.of(context).primaryColor
: null,
child: Text(
_items[index],
style: TextStyle(fontSize: 20),
),
),
),
);
},
),
)
],
),
),
),
);
}
}

Flutter - Provider - Clearing Data itself when navigate

When I in a page and added some quantity and navigate to another page and come back to added more quantity data is cleared.
Here's my code.
add_inv_stream.dart
class AddInvStream extends StatelessWidget {
const AddInvStream({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
FirebaseServices services = FirebaseServices();
final provider = Provider.of<InventoryProvider>(context);
return StreamBuilder<QuerySnapshot>(
stream: services.inventory
.where('fishType', isEqualTo: provider.inventoryData['fishType'])
.where('status', isEqualTo: true)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Center(child: Text('Something wrong!'));
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.data!.size == 0) {
return const Center(
child: Text('No inventories'),
);
}
return AddInvData(snapshot: snapshot, services: services);
},
);
}
}
add_inv_data.dart
class AddInvData extends StatefulWidget {
final AsyncSnapshot<QuerySnapshot<Object?>> snapshot;
final FirebaseServices services;
const AddInvData({Key? key, required this.snapshot, required this.services})
: super(key: key);
#override
State<AddInvData> createState() => _AddInvDataState();
}
class _AddInvDataState extends State<AddInvData> {
final _qty = TextEditingController();
List sellerList = [];
#override
Widget build(BuildContext context) {
final providerr = Provider.of<InventoryProvider>(context);
return ListView.builder(
padding: const EdgeInsets.all(15.0),
physics: const ScrollPhysics(),
shrinkWrap: true,
itemCount: widget.snapshot.data!.size,
itemBuilder: (context, index) {
Map<String, dynamic> sellerData =
widget.snapshot.data!.docs[index].data() as Map<String, dynamic>;
int sellerQty = int.parse(sellerData['qty']);
return InkWell(
onTap: () {
showDialog(
context: context,
useRootNavigator: false,
builder: (context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40),
),
elevation: 16,
child: Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Quantity in kg: '),
const SizedBox(width: 10),
Container(
height: 60,
width: 60,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
),
child: TextFormField(
controller: _qty,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
border: InputBorder.none,
),
),
),
],
),
const SizedBox(height: 50),
TextButton(
onPressed: () async {
Map<String, dynamic> seller = {
'date': sellerData['date'],
'qty': _qty.text,
};
sellerList.add(seller);
providerr.getData(sellerList: sellerList);
print(providerr.inventoryData['sellerList']);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const InvDetails(),
));
},
child: const Text('ASSIGN'),
),
],
),
),
);
},
);
},
child: Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
sellerData['date'],
style: const TextStyle(fontSize: 18),
),
Text(
'${sellerData['qty']} kg',
style: const TextStyle(fontSize: 18),
),
],
),
),
);
},
);
}
}
inv_details.dart
class InvDetails extends StatelessWidget {
const InvDetails({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: TextButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const AddInv(),
));
},
child: const Text('Add Inventory'),
),
),
);
}
}
inv_provider.dart
class InventoryProvider with ChangeNotifier {
Map<String, dynamic> inventoryData = {};
getData({List? sellerList}) {
if (sellerList != null) {
inventoryData['sellerList'] = sellerList;
}
notifyListeners();
}
}
Here printing at the first
[{date: 10/31/2022, qty: 1}]
When I navigate to InvDetails from AddInvData and when the button is clicked it's printing
[{date: 11/25/2022, qty: 1}]
Data is not updating
But if I didn't navigate.
i.e If I stay in AddInvData and added quantity it is updating.
inv_data.dart (Added textbutton part only ) removed navigate
TextButton(
onPressed: () async {
Map<String, dynamic> seller = {
'date': sellerData['date'],
'qty': _qty.text,
};
sellerList.add(seller);
providerr.getData(sellerList: sellerList);
print(providerr.inventoryData['sellerList']);
},
prints
[{date: 10/31/2022, qty: 1}]
[{date: 10/31/2022, qty: 1}, {date: 11/25/2022, qty: 1}]
Why this is not hapenning when navigate and come back to previous page?

Flutter Sqflite Toggling between Screens based on Login Status creates null operator used on null value error

I am trying to toggle between Login Screen and HomeScreen based on the user status. The logic seems to be working as long as I don't put HomeScreen.
I replaced HomeScreen with a different screen to check and the app works as it should. It displays different screens on hot restart based on the user's login status. But as soon as I try to put HomeScreen I get null operator used on null value error.
Here is the toggle logic.
class Testing extends StatefulWidget {
const Testing({super.key});
#override
State<Testing> createState() => _TestingState();
}
class _TestingState extends State<Testing> {
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: TodoServiceHelper().checkifLoggedIn(),
builder: ((context, snapshot) {
if (!snapshot.hasData) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
}
if (snapshot.hasError) {
print(snapshot.hasError);
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
}
if (snapshot.data!.isNotEmpty) {
print(snapshot.data);
return RegisterPage();
// returning HomePage gives null check operator used on null value error
} else
return Login();
}),
);
}
}
Here is the HomeScreen
class HomePage extends StatefulWidget {
String? username;
HomePage({this.username});
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final GlobalKey<FormState> formKey = GlobalKey();
TextEditingController termController = TextEditingController();
void clearText() {
termController.clear();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
onPressed: () {
User loginUser =
User(username: widget.username.toString(), isLoggedIn: false);
TodoServiceHelper().updateUserName(loginUser);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (BuildContext context) => Login()));
},
icon: Icon(Icons.logout),
color: Colors.white,
)
],
title: FutureBuilder(
future: TodoServiceHelper().getTheUser(widget.username!),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
}
return Text(
'Welcome ${snapshot.data!.username}',
style: TextStyle(color: Colors.white),
);
}),
),
body: SingleChildScrollView(
child: Column(children: [
Column(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Form(
key: formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: termController,
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(),
labelText: 'search todos',
),
),
TextButton(
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ShowingSerachedTitle(
userNamee: widget.username!,
searchTerm: termController.text,
)),
);
print(termController.text);
clearText();
setState(() {});
},
child: Text(
'Search',
)),
Divider(
thickness: 3,
),
],
),
),
),
],
),
Container(
child: Stack(children: [
Positioned(
bottom: 0,
child: Text(
' done Todos',
style: TextStyle(fontSize: 12),
),
),
IconButton(
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CheckingStuff(userNamee: widget.username!)),
);
setState(() {});
},
icon: Icon(Icons.filter),
),
]),
),
Divider(
thickness: 3,
),
Container(
child: TodoListWidget(name: widget.username!),
height: 1000,
width: 380,
)
]),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Color.fromARGB(255, 255, 132, 0),
onPressed: () async {
await showDialog(
barrierDismissible: false,
context: context,
builder: ((context) {
return AddNewTodoDialogue(name: widget.username!);
}),
);
setState(() {});
},
child: Icon(Icons.add),
),
);
}
}
The function used to return user with loginStatus true
Future<List<User>> checkifLoggedIn() async {
final Database db = await initializeDB();
final List<Map<String, Object?>> result = await db.query(
'users',
where: 'isLoggedIn = ?',
whereArgs: ['1'],
);
List<User> filtered = [];
for (var item in result) {
filtered.add(User.fromMap(item));
}
return filtered;
}
the problem is here
you used ! sign on a nullable String , and this string is nullable,
try to use this operation (??) so make it
widget.username??"" by this line you will check if the user name is null it will be replaced by an empty string.

Expected a value of type 'String', but got one of type 'Null' StreamBuilder<QuerySnapshot<Object?>>

I trying create a contact list to be displayed on my screen as a user edit of delete his details. I got this error and UI doesn't show anything. The error is : Expected a value of type 'String', but got one of type 'Null'
here is where error happens:
---dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
class contactlist extends StatefulWidget {
const contactlist({ Key? key }) : super(key: key);
#override
State<contactlist> createState() => _contactlistState();
}
class _contactlistState extends State<contactlist> {
final Stream<QuerySnapshot>_myUserContacts =
FirebaseFirestore.instance.collection('userContact').snapshots();
#override
Widget build(BuildContext context) {
TextEditingController _nameFieldcntroler = TextEditingController();
TextEditingController _phoneNumFieldcntroler = TextEditingController();
TextEditingController _EmailFieldcntroler = TextEditingController();
TextEditingController _AgeFieldcntroler = TextEditingController();
void _delete(docId){
FirebaseFirestore.instance
.collection("userContact")
.doc(docId)
.delete()
.then((value) => print("deleted"));
}
void _update(data){
var collection = FirebaseFirestore.instance.collection("userContact");
_nameFieldcntroler.text = data["names"];
_phoneNumFieldcntroler.text = data["phoneNumber"];
_EmailFieldcntroler.text = data["email"];
_AgeFieldcntroler.text = data["age"];
showDialog(context: context,
builder: (_) => AlertDialog(
title: Text("Update"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller:_nameFieldcntroler,
),
TextField(
controller:_phoneNumFieldcntroler,
),
TextField(
controller:_EmailFieldcntroler,
),
TextField(
controller:_AgeFieldcntroler,
),
TextButton(
onPressed: (){
collection.doc(data["doc_Id"])
.update({
"names": _nameFieldcntroler.text,
"phoneNumber": _phoneNumFieldcntroler.text,
"email": _EmailFieldcntroler.text,
"age": _AgeFieldcntroler.text,
});
Navigator.pop(context);
},
child: Text("Update")),
]),
)
);
}
return StreamBuilder(
stream: _myUserContacts,
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot<Object?>> snapshot){
if (snapshot.hasError){
return const Text("Something went wrong");
}
if(snapshot.connectionState == ConnectionState.waiting){
return const Center(child: CircularProgressIndicator());
}
if(snapshot.hasData){
return Row(
children: [
Expanded(
child: SizedBox(
height: (MediaQuery.of(context).size.height),
width: (MediaQuery.of(context).size.width),
child: ListView(
children: snapshot.data!.docs
.map((DocumentSnapshot documentSnapshot) {
Map<String, dynamic> data = documentSnapshot.data()! as Map<
String, dynamic>;
return Column(
children: [
Card(
child: Column(
children:[
ListTile(
title: Text(data['names']),
subtitle:Text(data['phoneNumber']),
),
ButtonTheme(
child: ButtonBar(
children:[
OutlineButton.icon(
onPressed:(){
_update(data);
},
icon: Icon(Icons.edit),
label: Text("Edit"),
),
OutlineButton.icon(
onPressed:(){
_delete(data["doc_Id"]);
},
icon: Icon(Icons.remove),
label: Text("Delete"),
)
],
),
),
],
)
)
],
);
}).toList(),
),
)
)
],
);
}else{
return(Text("No data"));
}
},
);
}
}
---dart
---dart
The following TypeErrorImpl was thrown building StreamBuilder<QuerySnapshot<Object?>>(dirty, dependencies: [MediaQuery], state: _StreamBuilderBaseState<QuerySnapshot<Object?>, AsyncSnapshot<QuerySnapshot<Object?>>>#1efa0):
Expected a value of type 'String', but got one of type 'Null'
The relevant error-causing widget was
StreamBuilder<QuerySnapshot<Object?>>
---dart

Flutter riverpod update state of specific index in ListView

I have an app that makes a post request to an API with data about drivers and orders. The initial page displays a list of drivers in individual list tiles. The list tile has a drop down option. Clicking on that option brings you to a new page with a list view of orders for that driver. Clicking on an individual order brings you to a form. On submitting and validating this form, I want to change the color of that orders text from red to green. Each Order has a submitted flag, and when it submits I would want to change that to true and then have the color change. When all the orders are green within an List View, I want the color of that driver to turn green. I've been going over riverpod tutorials and documentation but can't quite figure out how to get this done. Can someone point me in the right direction?
main.dart
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: DriversPage(),
);
}
}
drivers.dart - This is where the drivers are displayed
class DriversPage extends StatelessWidget {
final HttpService httpService = HttpService();
var colorChoice = Colors.red;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFFAFAFA),
appBar: AppBar(
title: Text("Drivers")
),
body: Container(
child: FutureBuilder(
future: httpService.getOrders(),
builder: (BuildContext context, AsyncSnapshot<List<Order>> snapshot) {
if (snapshot.hasData) {
List<Order> orders = snapshot.data;
return ListView(
children: orders.map((Order order) => Card(child: ExpansionTile(
title: Text(order.driver, style: TextStyle(color: colorChoice),),
children: <Widget>[
Container(
alignment: Alignment.center,
margin: EdgeInsets.all(10.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(2.0),
border: Border.all(color: Colors.black26)
),
child: ListTile(title: Text("Orders"),
trailing: Icon(Icons.keyboard_arrow_right),
onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => OrdersState(driverName: order.driver, driverOrders: order.orders))),),
),
],
))).toList(),
);
}
return Center(child: CircularProgressIndicator());
}),
));
}
}
orders.dart - This is where the orders for a driver are displayed. I originally had it as a stateful widget but turned it into a Consumer Widget and took an attempt at making a provider but was lost on how to handle it in a listview like this. As you can see here I am using the ternary operator for the text color based on item.submitted
final driverListProvider = StateNotifierProvider((ref) => new DriverListTest());
class OrdersState extends ConsumerWidget {
final String driverName;
final List<OrderElement> driverOrders;
const OrdersState({Key key, this.driverName, this.driverOrders}) : super(key: key);
#override
Widget build(BuildContext context, ScopedReader watch) {
return Scaffold(
appBar: AppBar(
title: Text(driverName),
),
body: ListView.builder(
itemCount: driverOrders.length,
itemBuilder: (context, index){
final item = driverOrders[index];
return Card(
key: UniqueKey(),
child: ListTile(title: Text(item.order, style: TextStyle(color: item.submitted? Colors.green : Colors.red),),
subtitle: Text('${item.company}\n${item.address}'),
onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => OrderForm(orderTitle: item.order,))),));
}),
);
}
}
orderform.dart - Only showing one field for the form, figured the rest was not neccessary, just need to show what happens on submit.
class OrderForm extends StatefulWidget {
final String orderTitle;
const OrderForm({this.orderTitle});
#override
_OrderFormState createState() => _OrderFormState();
}
class _OrderFormState extends State<OrderForm> {
#override
final _formKey = GlobalKey<FormState>();
final _orderModel = Order();
List<String> _pickerNames = ['Loader 1', 'Loader 2', 'Loader 3', 'Loader 4'];
String _selectedPickedBy;
String _selectedCheckedBy;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: Colors.blueGrey,title: Center(
child: Text(widget.orderTitle),
),),
floatingActionButton: FloatingActionButton(
child: Icon(
Icons.delete
),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
scrollable: true,
title: Text('Login'),
content: Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(
labelText: 'Reason',
icon: Icon(Icons.account_box),
),
),
TextFormField(
decoration: InputDecoration(
labelText: 'Reason 1',
icon: Icon(Icons.email),
),
),
TextFormField(
decoration: InputDecoration(
labelText: 'Reason 2',
icon: Icon(Icons.message),
),
),
],
),
),
),
actions: [
RaisedButton(
child: Text("Submit"),
onPressed: () {
})
],
);
});
}
),
body: Container(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: Builder(
builder: (context) => Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
DropdownButtonFormField(
isExpanded: true,
hint: Text('Picked By'),
value: _selectedPickedBy,
onChanged: (newValue){
setState(() {
_selectedPickedBy = newValue;
});
},
validator: (value) => value == null
? 'Picked By Required' : null,
items: _pickerNames.map((picker) {
return DropdownMenuItem(
child: new Text(picker),
value: picker,
);
}).toList(),
onSaved: (value) => setState(() => _orderModel.pickedBy = value) ,
),
Container(
padding: const EdgeInsets.symmetric(
vertical: 16.0, horizontal: 16.0
),
child: RaisedButton(
onPressed: (){
final form = _formKey.currentState;
if (form.validate()){
form.save();
Navigator.pop(context,);
}
},
child: Text("Submit"),
),
)
],
)),
),
)
);
}
}
ordermodel.dart - This is the model for the drivers and orders when making http requests to my api. At the bottom you can see where I attempt at making a statenotifier and what I'm trying to with accepting a list of OrderElement(The list of orders).
List<Order> orderFromJson(String str) => List<Order>.from(json.decode(str).map((x) => Order.fromJson(x)));
String orderToJson(List<Order> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Order {
Order({
this.driver,
this.orders,
});
String driver;
List<OrderElement> orders;
factory Order.fromJson(Map<String, dynamic> json) => Order(
driver: json["Driver"],
orders: List<OrderElement>.from(json["Orders"].map((x) => OrderElement.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"Driver": driver,
"Orders": List<dynamic>.from(orders.map((x) => x.toJson())),
};
}
class OrderElement {
OrderElement({
this.order,
this.company,
this.address,
this.submitted,
this.index,
});
String order;
String company;
String address;
bool submitted;
num index;
factory OrderElement.fromJson(Map<String, dynamic> json) => OrderElement(
order: json["Order"],
company: json["Company"],
address: json["Address"],
submitted: json["submitted"],
index: json["index"]
);
Map<String, dynamic> toJson() => {
"Order": order,
"Company": company,
"Address": address,
};
}
class DriverListTest extends StateNotifier<List<OrderElement>> {
DriverListTest([List<OrderElement> drivers1]) : super(drivers1 ?? []);
void onSubmit(num index) {
state = [
for(final currentOrder in state)
if (currentOrder.index == index)
OrderElement(
order: currentOrder.order,
company: currentOrder.company,
address: currentOrder.address,
submitted: !currentOrder.submitted,
index: currentOrder.index,
)
else
currentOrder,
];
}
}
Don't know if my Http class is necessary but let me know if it is. I tried following https://www.refactord.com/guides/riverpod-state-management-explained and How to set the state of a widget at an index in a listview.builder in flutter how to handle individual widgets but again I just got lost. Any help would be greatly appreciated! Thanks in advance.