Here is the child class that receives from its parent the index data that identifies the box to modify
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> {
final int indexitem = 0;
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(indexitem, newNOTE);
Navigator.of(context).pop();
}
This way works but I don't have the index of the parent, I give it to him
final int indexitem = 0; <--- Works perfectly with my function patientbox.put() it receives the index
boxPatient.put(indexitem, newNOTE);
I would like to give indexbox the value of index but I don't know how to do it or if there is another way
final int indexitem = ??? <---- add the value of index
boxPatient.put(indexitem, newNOTE);
obviously I can't use index directly in the function boxPatient.put()
Thank you very much for your help
To read variables from the widget inside the state, you can simply refer to widget.<variable>. So in your example
boxPatient.put(widget.index, newNOTE);
Related
I am sending 2 parameters restaurantDetails.rest_latitude and restaurantDetails.rest_longitude to a class to get the map details
BarMapWidget(restaurantDetails.rest_latitude, restaurantDetails.rest_longitude),
In the class I have a stateful widget
class BarMapWidget extends StatefulWidget {
String restLatitude;
String restLongitude;
BarMapWidget(this.restLatitude, this.restLongitude, {Key? key}) : super(key: key);
#override
_BarMapWidgetState createState() => _BarMapWidgetState();
}
I am passing a string so I know I have to make it a double
Here is the extended class,
class _BarMapWidgetState extends State<BarMapWidget> {
// Destination Longitude
final double _destLatitude = restLatitude;
final double _destLongitude = restLongitude;
void initState() {
// Add destination marker
_addMarker(
LatLng(_destLatitude, _destLongitude),
"destination",
// BitmapDescriptor.defaultMarkerWithHue(90),
BitmapDescriptor.defaultMarker
);
super.initState();
}
Which give me a Undefined name 'restLatitude'. and Undefined name 'restLongitude'.
How can I access the variable in BarMapWidget?
Your restLatitude and restLongitude on widget level, try using widget.variableName. Also, those aren't matching datatype.
If you need double convert BarMapWidget variable to double.
To initialize on state level you can trick with using late or use initState;
class BarMapWidget extends StatefulWidget {
final double restLatitude;
final double restLongitude;
const BarMapWidget(this.restLatitude, this.restLongitude, {Key? key})
: super(key: key);
#override
_BarMapWidgetState createState() => _BarMapWidgetState();
}
class _BarMapWidgetState extends State<BarMapWidget> {
// Destination Longitude
late final double _destLatitude = widget.restLatitude;
late final double _destLongitude = widget.restLongitude;
Just add in
widget.restLatitude
this is my code and i want to access to "initialValue" propierty from the StatefulWudget but for some reason marks a error in counter = widget.initialValue
the image with the error from vs code.
I'm following a course and i don't know if something change in the new versions, cause all the questions that i found use the same code.
class MyCounter extends StatefulWidget{
final int initialValue;
const MyCounter({Key? key, this.initialValue = 0}) : super(key: key);
#override
State createState(){ //puede ser lamda => MyCounterState();
return MycounterState();
}
}
class MycounterState extends State{
int counter = 0;
#override
void initState() {
// TODO: implement initState
super.initState();
counter = widget.initialValue;
}
...
Or do i have an error in a different part of the code?
for someone with the same problem the solution(found in the discord offical flutter server) was
"Your state must have a type argument containing the widget"
class MyCounter extends StatefulWidget{
final int initialValue;
const MyCounter({Key? key, this.initialValue = 0}) : super(key: key);
#override
State<MyCounter> createState(){ //puede ser lamda => MyCounterState();
return MycounterState();
}
}
class MycounterState extends State<MyCounter>{
int counter = 0;
#override
void initState() {
// TODO: implement initState
super.initState();
counter = widget.initialValue;
}
just need to change State to State<MyCounter> in the "createState()" from MyCounter class and the "extends State{" from MyCounterState class
I want to get the data from the constructor and passes it to a variable.
I dont want it to be listed...
Class:
class ListaProjetos extends StatefulWidget {
ListaProjetos({Key key, this.title, this.jsonData}) : super(key: key);
static const String routeName = "/ListaProjetos";
final String title;
final List jsonData;
#override
_ListaProjetosState createState() => _ListaProjetosState();
}
I want to:
class _ListaProjetosState extends State<ListaProjetos> {
var message = widget.jsonData;
print(message);
//HERE I WANT TO PRINT ALL JSON DATA
}
Inside the class you need create a method and place the variables initialization, for example:
#override
void initState() {
var message = widget.jsonData;
print(message);
}
Or you can declare the var outside of the method to use it in others methods.
var message;
#override
void initState() {
message = widget.jsonData;
print(message);
}
How do I update my UI when the value change in another stateful widget?.
I created a stateful class (Test2) which build a widget. Then in my main class, I have a list of Test2 widget. Finally, I am iterating thru the list and rendering the Test2 widget.
However, I want to update a value in one of Test2 widget and then have the main UI update accordingly.
How can I do that?
FILE:test2.dart
class Test2 extends StatefulWidget {
Test2({this.responseId, this.message});
final String responseId;
final String message;
bool strike =false;
#override
_Test2State createState() => _Test2State();
}
class _Test2State extends State<Test2> {
#override
Widget build(BuildContext context) {
return Container(
child: Text(
widget.responseId + widget.message,
style: (widget.strike)?TextStyle(decoration: TextDecoration.none):TextStyle(decoration: TextDecoration.underline)
),
);
}
}
File :home.dart
MAIN CLASS
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Test2> _counter =List();
int cnt =0;
#override
void initState() {
super.initState();
_counter.add(Test2(message: "message",responseId:"1"));
_counter.add(Test2(message: "message",responseId:"2"));
_counter.add(Test2(message: "message",responseId:"3"));
}
In my BUILD METHOD
for(int i=0;i<_counter.length;i++)...[
_counter[i]
],
BUTTON CLICK
void _incrementCounter() {
for(int i=0;i<_counter.length;i++){
if(_counter[i].responseId =="1"){
_counter[i].strike =true;
}
}
setState(() {
});
}
You can use ValueNotifier to rebuild the listeners.
Decalre a ValueNotifier<bool> in the Text2 class and initialize it.
ValueNotifier<bool> strikeNotifier = ValueNotifier(false);
then use ValueListenableBuilder to wrap the widget that you want to rebuild when value of strike changes.
ValueListenableBuilder(valueListenable: strikeNotifier, builder: (_, result, widget) => Text(...),)
And create a method for updating the value of strike, also for comparing the old and new values and update the value of ValueNotifier with the comparison result.
void updateStrike(bool value){
var result = (strike == value);
strike = value;
strikeNotifier.value = result;
}
So you can update the value of strike with updateStrike() in _incrementCounter() to notify the Text2 widgets for rebuilding.
I have 2 screens in my Flutter app: a list of records and a screen for creating and editing records.
If I pass an object to the second screen that means I am going to edit this and if I pass null it means that I am creating a new item. The editing screen is a Stateful widget and I am not sure how to use this approach https://flutter.io/cookbook/navigation/passing-data/ for my case.
class RecordPage extends StatefulWidget {
final Record recordObject;
RecordPage({Key key, #required this.recordObject}) : super(key: key);
#override
_RecordPageState createState() => new _RecordPageState();
}
class _RecordPageState extends State<RecordPage> {
#override
Widget build(BuildContext context) {
//.....
}
}
How can I access recordObject inside _RecordPageState?
To use recordObject in _RecordPageState, you have to just write widget.objectname like below
class _RecordPageState extends State<RecordPage> {
#override
Widget build(BuildContext context) {
.....
widget.recordObject
.....
}
}
Full Example
You don't need to pass parameters to State using it's constructor.
You can easily access these using widget.myField.
class MyRecord extends StatefulWidget {
final String recordName;
const MyRecord(this.recordName);
#override
MyRecordState createState() => MyRecordState();
}
class MyRecordState extends State<MyRecord> {
#override
Widget build(BuildContext context) {
return Text(widget.recordName); // Here you direct access using widget
}
}
Pass your data when you Navigate screen :
Navigator.of(context).push(MaterialPageRoute(builder: (context) => MyRecord("WonderWorld")));
class RecordPage extends StatefulWidget {
final Record recordObject;
RecordPage({Key key, #required this.recordObject}) : super(key: key);
#override
_RecordPageState createState() => new _RecordPageState(recordObject);
}
class _RecordPageState extends State<RecordPage> {
Record recordObject
_RecordPageState(this. recordObject); //constructor
#override
Widget build(BuildContext context) {. //closure has access
//.....
}
}
example as below:
class nhaphangle extends StatefulWidget {
final String username;
final List<String> dshangle;// = ["1","2"];
const nhaphangle({ Key key, #required this.username,#required this.dshangle }) : super(key: key);
#override
_nhaphangleState createState() => _nhaphangleState();
}
class _nhaphangleState extends State<nhaphangle> {
TextEditingController mspController = TextEditingController();
TextEditingController soluongController = TextEditingController();
final scrollDirection = Axis.vertical;
DateTime Ngaysx = DateTime.now();
ScrollController _scrollController = new ScrollController();
ApiService _apiService;
List<String> titles = [];
#override
void initState() {
super.initState();
_apiService = ApiService();
titles = widget.dshangle; //here var is call and set to
}
I have to Navigate back to any one of the screens in the list pages but when I did that my onTap function stops working and navigation stops.
class MyBar extends StatefulWidget {
MyBar({this.pageNumber});
final pageNumber;
static const String id = 'mybar_screen';
#override
_MyBarState createState() => _MyBarState();
}
class _MyBarState extends State<MyBar> {
final List pages = [
NotificationScreen(),
AppointmentScreen(),
RequestBloodScreen(),
ProfileScreen(),
];
#override
Widget build(BuildContext context) {
var _selectedItemIndex = widget.pageNumber;
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
elevation: 0,
backgroundColor: Colors.white,
unselectedItemColor: Colors.grey.shade700,
selectedItemColor: Color(kAppColor),
selectedIconTheme: IconThemeData(color: Color(kAppColor)),
currentIndex: _selectedItemIndex,
type: BottomNavigationBarType.fixed,
onTap: (int index) {
setState(() {
_selectedItemIndex = index;
});
},
You should use a Pub/Sub mechanism.
I prefer to use Rx in many situations and languages. For Dart/Flutter this is the package: https://pub.dev/packages/rxdart
For example, you can use a BehaviorSubject to emit data from widget A, pass the stream to widget B which listens for changes and applies them inside the setState.
Widget A:
// initialize subject and put it into the Widget B
BehaviorSubject<LiveOutput> subject = BehaviorSubject();
late WidgetB widgetB = WidgetB(deviceOutput: subject);
// when you have to emit new data
subject.add(deviceOutput);
Widget B:
// add stream at class level
class WidgetB extends StatefulWidget {
final ValueStream<LiveOutput> deviceOutput;
const WidgetB({Key? key, required this.deviceOutput}) : super(key: key);
#override
State<WidgetB> createState() => _WidgetBState();
}
// listen for changes
#override
void initState() {
super.initState();
widget.deviceOutput.listen((event) {
print("new live output");
setState(() {
// do whatever you want
});
});
}
In my app, often instead of using stateful widgets, I use mainly ChangeNotifierProvider<T> in main.dart, some model class
class FooModel extends ChangeNotifier {
var _foo = false;
void changeFooState() {
_foo = true;
notifyListeners();
}
bool getFoo () => _foo;
}
and
var foo = context.read<FooModel>();
# or
var foo = context.watch<FooModel>();
in my stateless widgets. IMO this gives me more precise control over the rebuilding upon runtime state change, compared to stateful widgets.
The recipe can be found in the official docs, the concept is called "lifting state up".