How to use Hive to modify only one value of ca class model? - flutter

Here is my problem when I add a new patient to my boxPatient everything is added with the constructor of my class Patient.
After creating a patient I would like to be able to add notes to him so add to the box of this patient with boxpatient.put(index, value)
However, when I add a new value with the Patient constructor it modifies all the other fields with null which is normal but I was wondering if there was a way to avoid modifying all the other fields and to modify only the listnote field
Here is the addition to my patient box of a new patient:
class PatientList extends StatefulWidget {
const PatientList({Key? key}) : super(key: key);
#override
State<PatientList> createState() => _PatientListState();
}
class _PatientListState extends State<PatientList> {
List<Patients> patientList = [];
late Box<Patients> boxPatient;
#override
void initState() {
super.initState();
boxPatient = Hive.box('Patient');
//boxPatient.clear();
print('Patient ${boxPatient.values}');
}
void _bottomnewpatient(BuildContext ctx) {
TextEditingController namecontroller = TextEditingController();
TextEditingController firstnamecontroller = TextEditingController();
TextEditingController dateofbirthcontroller = TextEditingController();
TextEditingController emailcontroller = TextEditingController();
TextEditingController phonenumbercontroller = TextEditingController();
void _submitData() {
final enteredname = namecontroller.text;
final enteredfirstname = firstnamecontroller.text;
final entereddateofbirth = dateofbirthcontroller.text;
final enteredemail = emailcontroller.text;
final enteredphonenumber = phonenumbercontroller.text;
if (enteredname.isEmpty ||
enteredfirstname.isEmpty ||
entereddateofbirth.isEmpty ||
enteredemail.isEmpty ||
enteredphonenumber.isEmpty) {
print('No input');
return;
}
final newPT = Patients(
name: enteredname,
firstname: enteredfirstname,
dateofbirth: entereddateofbirth,
email: enteredemail,
numero: enteredphonenumber,
date: DateTime.now(),
id: DateTime.now().millisecondsSinceEpoch,
//id: DateTime.now().millisecondsSinceEpoch,
//listOfNotes: [],
);
boxPatient.add(newPT);
Navigator.of(context).pop();
}
And here is the addition of a new note to the patient box pointed by the index:
The problem here is that I call my constructor Patients() so it rebuilds all my fields how to avoid that.
With this builder also don't have the possibility to add more notes as it rebuilds each time.
class InformationPatient extends StatefulWidget {
final Patients patients;
final int index;
const InformationPatient(this.patients, this.index, {Key? key})
: super(key: key);
#override
State<InformationPatient> createState() => _InformationPatientState();
}
class _InformationPatientState extends State<InformationPatient> {
late Box<Patients> boxPatient;
#override
void initState() {
super.initState();
boxPatient = Hive.box('Patient');
}
void _addNote(String newtitle, String newnote, String newconclusion) {
final newNOTE = Patients(
listOfNotes: [
ListNote(title: newtitle, note: newnote, conclusion: newconclusion)
],
);
boxPatient.put(widget.index, newNOTE);
Navigator.of(context).pop();
}
and here is the class model:
import 'package:hive_flutter/hive_flutter.dart';
part 'listpatient.g.dart';
#HiveType(typeId: 0)
class Patients {
#HiveField(0)
final String? name;
#HiveField(1)
final String? firstname;
#HiveField(3)
final String? dateofbirth;
#HiveField(4)
final String? email;
#HiveField(5)
final String? numero;
#HiveField(6)
final DateTime? date;
#HiveField(7)
final int? id;
#HiveField(8)
final List<ListNote>? listOfNotes;
const Patients({
this.name,
this.firstname,
this.dateofbirth,
this.email,
this.numero,
this.date,
this.id,
this.listOfNotes,
});
}
#HiveType(typeId: 10)
class ListNote {
#HiveField(1)
final String? title;
#HiveField(2)
final String? note;
#HiveField(3)
final String? conclusion;
ListNote({
this.title,
this.note,
this.conclusion,
});
}
Thank you very much for your help! :)

Related

how can i place forloop so that i dont get error?

how can i use forloop to generate values of data variable please help i am a beginner
class Mentions extends StatefulWidget {
const Mentions({
Key? key,
this.width,
this.height,
required this.fullname,
required this.username,
required this.photourl,
}) : super(key: key);
final double? width;
final double? height;
final List<String> fullname;
final List<String> username;
final List<String> photourl;
#override
_MentionsState createState() => _MentionsState();
}
class _MentionsState extends State<Mentions> {
List<Map<String, dynamic>> data = [];
void data1(
for(int i = 0; i< widget.fullname.length; i++) {
data.add({"Full Name": widget.fullname[i], "username": widget.username[i], "photourl" :widget.photourl[i] });
}
)
);
#override
Widget build(BuildContext context) {
return Container();
}
}
you can place your method inside initState
class _MentionsState extends State<Mentions> {
List<Map<String, dynamic>> data = [];
void data1 (){
for(int i = 0; i< widget.fullname.length; i++) {
data.add({
"Full Name": widget.fullname[i],
"username": widget.username[i],
"photourl" :widget.photourl[i]
});
}
)
}
#override
void initState() {
super.initState();
data1();
}
#override
Widget build(BuildContext context) {
return Container();
}
}
try this:
class Mentions extends StatefulWidget {
Mentions({
required this.fullname,
required this.username,
required this.photourl,
this.width,
this.height,
Key? key,
}) : super(key: key) {
for (var i = 0; i < fullname.length; i++) {
users.add({
'Full Name': fullname[i],
'username': username[i],
'photourl': photourl[i]
});
}
}
final double? width;
final double? height;
final List<String> fullname;
final List<String> username;
final List<String> photourl;
late final List<Map<String, dynamic>> users;
#override
_MentionsState createState() => _MentionsState();
}
class _MentionsState extends State<Mentions> {...}
then you can just use widget.users in _MentionsState. but you can even not set all this lists in widget constructor, do mapping to users before, and set to widget constructor just one list with users. and do you really need stateful widget instead of stateless?

how to target an element of our class with hive to change it

good morning,
I don't know how to access an element of my boxHive without rebuilding it
I would like to be able to update some information without changing the existing one
Here is how I do it here, I use the constructor of my model class to add notes but it rebuilds all my class at the same time I would like it to rebuild only ListNote
class InformationPatient extends StatefulWidget {
final Patients patients;
final int index;
const InformationPatient(this.patients, this.index, {Key? key})
: super(key: key);
#override
State<InformationPatient> createState() => _InformationPatientState();
}
class _InformationPatientState extends State<InformationPatient> {
late Box<Patients> boxPatient;
#override
void initState() {
super.initState();
boxPatient = Hive.box('Patient');
}
void _addNote(String newtitle, String newnote, String newconclusion) {
final newNOTE = Patients(
listOfNotes: [
ListNote(title: newtitle, note: newnote, conclusion: newconclusion)
],
);
boxPatient.put(widget.index, newNOTE);
Navigator.of(context).pop();
}
And here is my class model
import 'package:hive_flutter/hive_flutter.dart';
part 'listpatient.g.dart';
#HiveType(typeId: 0)
class Patients {
#HiveField(0)
final String? name;
#HiveField(1)
final String? firstname;
#HiveField(3)
final String? dateofbirth;
#HiveField(4)
final String? email;
#HiveField(5)
final String? phonenumber;
#HiveField(6)
final DateTime? date;
#HiveField(7)
final int? id;
#HiveField(8)
final List<ListNote>? listOfNotes;
const Patients({
this.name,
this.firstname,
this.dateofbirth,
this.email,
this.phonenumber,
this.date,
this.id,
this.listOfNotes,
});
}
#HiveType(typeId: 10)
class ListNote {
#HiveField(1)
final String? title;
#HiveField(2)
final String? note;
#HiveField(3)
final String? conclusion;
ListNote({
this.title,
this.note,
this.conclusion,
});
}
Actually Hive offers only Write and Read operations, as you can see from its official documentation for flutter
so in order to update an Object in your boxPatient Box you need to get it with this:
Patients patients = boxPatient.get(widget.index);
then make your edits over it, then save it again on that same key:
boxPatient.put(widget.index, patients);
you can say we just updated it with this process.

How to display the middle element of a list in Flutter?

I have a similar widget for CupertinoPicker, but it was made by hand. I need to make the middle element of the list be selected by default, not the initial one as it is now. I've tried different options but haven't been able to do it yet. Please tell me how to implement this, I will be grateful for the help?
widget
class WheelSpeedPicker extends StatefulWidget {
final Function(dynamic) onValueChanged;
final int? startPosition;
final double itemSize;
final double? listHeight;
final int currentPosition;
final double? listWidth;
final FixedExtentScrollController? controller;
const WheelSpeedPicker({
Key? key,
required this.onValueChanged,
required this.currentPosition,
required this.itemSize,
this.startPosition,
this.listHeight,
this.controller,
this.listWidth,
}) : super(key: key);
#override
_WheelTimePickerState createState() {
return _WheelTimePickerState();
}
}
class _WheelTimePickerState extends State<WheelSpeedPicker> {
FixedExtentScrollController? fixedExtentScrollController;
int? currentPosition;
#override
void initState() {
super.initState();
currentPosition = widget.currentPosition;
fixedExtentScrollController = widget.controller ??
FixedExtentScrollController(initialItem: currentPosition ?? 0);
}
void _listener(int position) {
setState(() {
currentPosition = position;
});
widget.onValueChanged(currentPosition);
}
#override
void initState() {
super.initState();
// swap this
// currentPosition = widget.currentPosition;
// with this
currentPosition = (time.length / 2).floor();
fixedExtentScrollController = widget.controller ??
FixedExtentScrollController(initialItem: currentPosition ?? 0);
}
Other than that, I think your widget would be more useful if you added the items list to the widget parameters:
class WheelSpeedPicker extends StatefulWidget {
final Function(dynamic) onValueChanged;
final List<String> items;
final int? startPosition;
final double itemSize;
final double? listHeight;
final int currentPosition;
final double? listWidth;
final FixedExtentScrollController? controller;
const WheelSpeedPicker({
Key? key,
required this.items,
required this.onValueChanged,
required this.currentPosition,
required this.itemSize,
this.startPosition,
this.listHeight,
this.controller,
this.listWidth,
}) : super(key: key);
And then you'd have a more coherent set of parameters, because you already have a startPosition in the interface.
#override
void initState() {
super.initState();
currentPosition = widget.startPosition;
fixedExtentScrollController = widget.controller ??
FixedExtentScrollController(initialItem: startPosition ?? 0);
}

boolean expression must not be null | Getting this error when i switch timerState to "true". "False" doesn't give an error, what went wrong?

I am getting bool value timerState through the constructor. When I print the value I get proper results (true or false).
I need to call the function _controller.start() when timerState() == true. However when it is true I get the error: "Failed assertion: boolean expression must not be null".
Surprisingly, when timerState is false, I am not getting this error.
Please help, where can be a problem.
Below is my code:
class PieChart extends StatefulWidget {
final String userId;
final String userName;
final bool timerState;
final Key key;
PieChart(
this.userId,
this.userName,
this.timerState,
{this.key});
#override
State<StatefulWidget> createState() => PieChartEmotionsState(
userId,
userName,
timerState,
);
}
class PieChartEmotionsState extends State {
final String userId;
final String userName;
final bool timerState;
final Key key;
PieChartEmotionsState(
this.userId,
this.userName,
this.timerState,
{this.key});
#override
Widget build(BuildContext context) {
CountDownController _controller = CountDownController();
int _duration = 10;
bool getTimerState() {
print('PIE CHART timerState: $timerState');
return timerState == true;
}
if (getTimerState()) {
_controller.start();
}
return Container(...
I have obviously tried a simpler way:
if(timerState) _controller.start();
even this:
if(timerState ?? false) _controller.start();
But it seems not to have any impact on the issue. I am getting the same error...
What could be the solution?
Many thanks in advance for your support.
Dan
You don't need co create copies of your widget classes variables in the State class. Access them as widget.variable
class PieChart extends StatefulWidget {
final String userId;
final String userName;
final bool timerState;
final Key key;
PieChart(
this.userId,
this.userName,
this.timerState,
{this.key});
#override
State<PieChart> createState() => _PieChartState();
}
class _PieChartState extends State<PieChart> {
bool getTimerState() {
print('PIE CHART timerState: ${widget.timerState}');
return widget.timerState == true;
}
#override
Widget build(BuildContext context) {
CountDownController _controller = CountDownController();
int _duration = 10;
if (getTimerState()) {
_controller.start();
}
return Container(...
and make sure you initialize timerState when creating your PieChart widget as it's declared final.
PieChart('userId', 'userName', true);
If you don't initialize it, it's set to null and the error you get is because you are checking if null == true in your getTimerState() method.

Set value of TextEditingController from navigator

In my first page I have this:
onPressed: () {
Navigator.push(context,MaterialPageRoute(
builder: (context) =>
UpdateAttackScreen(
idAttack: idAttack,
title: title,
descriptionAttack:descriptionAttack,
indexSensations:indexSensations)));
},
in the second page where I want to receive this params:
class UpdateAttackScreen extends StatefulWidget {
final String idAttack;
final String title;
final String descriptionAttack;
final List<dynamic> indexSensations;
UpdateAttackScreen(
{Key key,
#required this.idAttack,
#required this.title,
#required this.descriptionAttack,
#required this.indexSensations})
: super(key: key);
#override
_UpdateAttackScreenState createState() => _UpdateAttackScreenState(idAttack, title, descriptionAttack, indexSensations);
}
class _UpdateAttackScreenState extends State<UpdateAttackScreen> {
String idAttack;
String title;
String descriptionAttack;
List<dynamic> indexSensations;
_UpdateAttackScreenState(idAttack, title, descriptionAttack, indexSensations);
TextEditingController _titleController = TextEditingController()..text = title;
TextEditingController _descriptionController = TextEditingController()..text = descriptionAttack;
The response error on title and descriptionAttack:
The instance member 'title' can't be accessed in an initializer.
Try replacing the reference to the instance member with a different expression
this code
TextEditingController _titleController = TextEditingController()..text = title;
TextEditingController _descriptionController = TextEditingController()..text = descriptionAttack;
replace with this
TextEditingController _titleController;
TextEditingController _descriptionController;
#override
void initState() {
super.initState();
_titleController = TextEditingController()..text = title;
_descriptionController = TextEditingController()..text = descriptionAttack;
}
Solution 1 :
Wrap _titleController with initState method
String title = '';
TextEditingController _titleController;
#override
void initState() {
_titleController..text = title;
super.initState();
}
Solution 2:
Transform the title variable into a static variable to be able to use it everywhere in your class
static String title = '';
TextEditingController _titleController = TextEditingController()..text = title ;
I fixed it!
class UpdateAttackScreen extends StatefulWidget {
final String idAttack;
final String title;
final String descriptionAttack;
final List<dynamic> indexSensations;
UpdateAttackScreen(
{Key key,
#required this.idAttack,
#required this.title,
#required this.descriptionAttack,
#required this.indexSensations})
: super(key: key);
#override
_UpdateAttackScreenState createState() => _UpdateAttackScreenState(idAttack, title, descriptionAttack, indexSensations);
}
class _UpdateAttackScreenState extends State<UpdateAttackScreen> {
String idAttack;
String title;
String descriptionAttack;
List<dynamic> indexSensations;
_UpdateAttackScreenState(idAttack, title, descriptionAttack, indexSensations);
TextEditingController _titleController;
TextEditingController _descriptionController;
Inside the TextFieldForm
initialValue: widget.title,