I have problem with checkbox to add parameter hit to POST data for API.
This is POST data sent when I clicked Save Button :
Map<String, String> params = {
'pet_name': petNameCtrl.text,
'pet_healths[0]': '3', //manual
'pet_healths[1]': '4', //manual
};
final response = await http.post(
Uri.parse(
"http://localhost:8000/api/v1/pet",
),
headers: {'Authorization': 'Bearer $token'},
body: params,
);
}
This is how my checkbox data called from API and the widget :
List<PetHealthModel> petHealths = [];
bool selectedPetHealth = false;
void fetchPetData() {
getDataHealth();
}
void getDataHealth() async {
final response = await http.get(
Uri.parse("http://localhost:8000/api/v1/pet_health"),
);
final metadata = PetHealthsMetadata.fromJson(jsonDecode(response.body));
setState(() => petHealths = metadata.data);
}
petHealths.isNotEmpty
? Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: petHealths.map((e) {
return CheckboxListTile(
title: Text(e.healthStatus),
value: selectedPetHealth,
onChanged: (bool? value) {
setState(() {
selectedPetHealth = value!;
});
}
);
}).toList(),
),
)
*btw I have secondary problem that if I select one of the checkbox, all checkbox will selected too. here's the picture
Please help, get stuck here for many days.
here's the sample for API :
PetHealthModel :
class PetHealthModel {
PetHealthModel({
required this.id,
required this.healthStatus,
});
final int id;
final String healthStatus;
factory PetHealthModel.fromJson(Map<String, dynamic> json) => PetHealthModel(
id: json["id"],
healthStatus: json["health_status"],
);
Map<String, dynamic> toJson() => {
"id": id,
"health_status": healthStatus,
};
}
class PetHealthsMetadata {
PetHealthsMetadata({
required this.data,
required this.code,
required this.msg,
});
final List<PetHealthModel> data;
final int code;
final String msg;
factory PetHealthsMetadata.fromJson(Map<String, dynamic> json) =>
PetHealthsMetadata(
data: List<PetHealthModel>.from(
json["data"].map((x) => PetHealthModel.fromJson(x))),
code: json["code"],
msg: json["msg"],
);
Map<String, dynamic> toJson() => {
"data": List<dynamic>.from(data.map((x) => x.toJson())),
"code": code,
"msg": msg,
};
}
*updated
Here is what it printed everytime the checkbox changed :
For final problem is how to made it auto add to Map<String, String> params ? see params code above
CodePudding user response:
Btw, for my second problem already solved.
this is what I add
List<int> customIds=[];
petHealths.isNotEmpty
? Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: petHealths.map((e) {
return CheckboxListTile(
title: Text(e.healthStatus),
value: customIds.contains(e.id),
onChanged: (bool? value) {
if (value == true) {
setState ((){
customIds.add(e.id);
});
} else {
setState((){
customIds.remove(e.id);
});
}
}
);
}).toList(),
),
)
CodePudding user response:
Ok from the code i have added a sample example for you, just copy and run the application to know how things are processing.
Solution Summary:
So you will get list of PetHealthModel and in that we can define a bool variable just for that model so that when that model gets rendered on the screen there will be a default value false and all the checkbox with no tick. and then when you click on the checkbox the specifc model isSelected is made true and only that item will be ticked.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Checkbox Example',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<PetHealthModel> petHealths = [];
@override
void initState() {
super.initState();
getDataHealth();
}
void getDataHealth() async {
// final response = await http.get(
// Uri.parse("http://localhost:8000/api/v1/pet_health"),
// );
// final metadata = PetHealthsMetadata.fromJson(jsonDecode(response.body));
//This above is the same where you get the data
// I have created a sample list
final list = [
PetHealthModel(id: 1, healthStatus: "Dont't no yet"),
PetHealthModel(id: 2, healthStatus: "Wash"),
PetHealthModel(id: 3, healthStatus: "cutting"),
PetHealthModel(id: 4, healthStatus: "styling"),
PetHealthModel(id: 4, healthStatus: "coloring"),
];
// you can use your metadata.data i am using the sample list for demo purpose.
setState(() => petHealths = list);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('heading'),
),
body: Column(
children: [
petHealths.isNotEmpty
? Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: petHealths.map((e) {
return CheckboxListTile(
title: Text(e.healthStatus),
value: e.isSelected,
onChanged: (bool? value) {
setState(() {
e.isSelected = value!;
});
});
}).toList(),
),
)
: Container(),
],
),
);
}
}
class PetHealthModel {
PetHealthModel({
required this.id,
required this.healthStatus,
this.isSelected = false,
// This is where you add the is selected item that means the status of every item can be modified.
});
final int id;
final String healthStatus;
bool isSelected;
// isSelected will not be in the below method because it is not coming from the api and this is just for ui change.
factory PetHealthModel.fromJson(Map<String, dynamic> json) => PetHealthModel(
id: json["id"],
healthStatus: json["health_status"],
);
Map<String, dynamic> toJson() => {
"id": id,
"health_status": healthStatus,
};
}
Let me know if it works for you