193
votes

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?

6
Possible duplicate of Passing Data to a Stateful WidgetHerohtar
how can we use 'recordObject' variable value in a function of _RecordPageState class?Kamlesh

6 Answers

312
votes

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
   .....
  }
}
47
votes

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")));
43
votes
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
   //.....
  }
}
4
votes

Often, you not only want to navigate to a new screen, but also pass data to the screen as well. For example, you might want to pass information about the item that’s been tapped.

In this example, create a list of todos. When a todo is tapped, navigate to a new screen (widget) that displays information about the Record. This recipe uses the following steps:

  • Define a RecordObject class.
  • Create a StatefulWidget. We call it RecordsScreen (for: Display a list of Records).
  • Create a detail screen that can display information about a Record.
  • Navigate and pass data to the detail screen.

Define a RecordObject class

class RecordsScreen extends StatefulWidget {
  List<RecordObject> records;
  RecordsScreen({Key key, @required this.records}) : super(key: key);
  @override
  _RecordsScreenState createState() => _RecordsScreenState();
}

class _RecordsScreenState extends State<RecordsScreen> {
  
  @override
  Widget build(BuildContext context) {
    widget.records = List<RecordObject>.generate(20,
          (i) => RecordObject(
        'Record $i',
        'A description of what needs to be done for Record $i',
      ),
    );
    return Scaffold(
      appBar: AppBar(
        title: Text('Records'),
      ),
      body: ListView.builder(
        itemCount:  widget.records.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text( widget.records[index].title),
            // When a user taps the ListTile, navigate to the DetailScreen.
            // Notice that you're not only creating a DetailScreen, you're
            // also passing the current todo through to it.
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => DetailScreen(recordObject:  widget.records[index]),
                ),
              );
            },
          );
        },
      ),
    );
  }
    

Create a detail screen - The title of the screen contains the title of the record, and the body of the screen shows the description.

class DetailScreen extends StatefulWidget {
  // Declare a field that holds the RecordObject.
  final RecordObject recordObject;

  // In the constructor, require a RecordObject.
  DetailScreen({Key key, @required this.recordObject}) : super(key: key);

  @override
  _DetailScreenState createState() => _DetailScreenState();
}

class _DetailScreenState extends State<DetailScreen> {
  @override
  Widget build(BuildContext context) {
    // Use the RecordObject to create the UI.
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.recordObject.title),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Text(widget.recordObject.description),
      ),
    );
  }
}

enter image description here

1
votes

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;
            });
          },
0
votes

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 
  }