Home > OS >  Unable to transfer a variable into another class
Unable to transfer a variable into another class

Time:01-03

In my program, users can create posts. And every post is called stuff. When an user created a stuff, automatically a stuffID assigns to that stuff. Also, I can list those stuffs in user's profile. When a user presses the edit button of one of their stuffs, a form appears in the screen. So the thing i want to do is when user press the edit button, I want to pass the stuffID from profile_sheet.dart class to update_stuff_form.dart class, so I can know to update the which stuff i will.

I have two .dart file. I used this function in my edit button in profile_sheet.dart file:

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => updateStuffForm(
      stuffID: data['stuffID'].toString())));

And I added my key function into update_stuff_form.dart like so:

class updateStuffForm extends StatefulWidget {
  //const updateStuffForm({Key? key}) : super(key: key);

  updateStuffForm({Key? key, this.stuffID}) : super(key: key);
  final String? stuffID;

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

And I called stuffID from end of the update_stuff_form.dart like this:

widget.stuffID

But whenever I run the program and press the edit button, It gaves me error below:

  ErrorSummary('No Material widget found.'),
        ErrorDescription(
          '${context.widget.runtimeType} widgets require a Material '
          'widget ancestor.\n'
          'In material design, most widgets are conceptually "printed" on '
          "a sheet of material. In Flutter's material library, that "
          'material is represented by the Material widget. It is the '
          'Material widget that renders ink splashes, for instance. '
          'Because of this, many material library widgets require that '
          'there be a Material widget in the tree above them.',
        ),
        ErrorHint(
          'To introduce a Material widget, you can either directly '
          'include one, or use a widget that contains Material itself, '
          'such as a Card, Dialog, Drawer, or Scaffold.',
        ),

Here is my full profile_sheet.dart file:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:unistuff_main/screens/home/update_stuff_form.dart';

class profileSheet extends StatefulWidget {
  const profileSheet({Key? key}) : super(key: key);

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

class _profileSheetState extends State<profileSheet> {
  final _formkey = GlobalKey<FormState>();

  //funcs

  @override
  Widget build(BuildContext context) {
    return Container(
      child: userStuffList(),
    );
  }
}

class userStuffList extends StatelessWidget {
  const userStuffList({Key? key}) : super(key: key);
  void _editStuff(BuildContext context) {
    //stuff_form link.
    showModalBottomSheet<dynamic>(
        isScrollControlled: true,
        context: context,
        builder: (context) {
          return Container(
              padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 60.0),
              child: updateStuffForm());
        });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _userStuffList(),
    );
  }
}

class _userStuffList extends StatelessWidget {
  void _editStuff(BuildContext context) {
    //stuff_form'a yönlendirme.
    showModalBottomSheet<dynamic>(
        isScrollControlled: true,
        context: context,
        builder: (context) {
          return Container(
              padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 60.0),
              child: updateStuffForm());
        });
  }

  @override
  Widget build(BuildContext context) {
    final FirebaseAuth auth = FirebaseAuth.instance;
    final User? user = auth.currentUser;
    final _uid = user!.uid;
    Query _stuffStream = FirebaseFirestore.instance
        .collection('Stuffs')
        .where('userID', isEqualTo: _uid);

    return Material(
      child: StreamBuilder<QuerySnapshot>(
          //veri akışı başlatılıyor
          //akış oluşturuluyor
          stream: _stuffStream.snapshots(),
          builder:
              (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
            if (snapshot.hasError) {
              return Text('Something is wrong.');
            }

            if (snapshot.connectionState == ConnectionState.waiting) {
              return Text("Loading");
            }

            return ListView(
              //showing the data
              children: snapshot.data!.docs.map((DocumentSnapshot document) {
                Map<String, dynamic> data =
                    document.data()! as Map<String, dynamic>;
                String stuffID = data['stuffID'];
                return ListTile(
                  title: Text(data['title']),
                  subtitle: Column(
                    children: <Widget>[
                      Text(data['details']),
                      TextButton(
                          child: const Text('Düzenle'),
                          onPressed: () {
                            Navigator.push(
                                context,
                                MaterialPageRoute(
                                    builder: (context) => updateStuffForm(
                                        stuffID: data['stuffID'].toString())));
                            _editStuff(context);
                          })
                    ],
                  ),
                );
              }).toList(),
            );
          }),
    );
  }
}

And my full update_stuff_form.dart (My key reference at first class, my widget.stuffID call all end of it.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
//import 'package:unistuff_main/screens/home/profile_sheet.dart';

class updateStuffForm extends StatefulWidget {
  //const updateStuffForm({Key? key}) : super(key: key);

  updateStuffForm({Key? key, this.stuffID}) : super(key: key);
  final String? stuffID;

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

class _updateStuffFormState extends State<updateStuffForm> {
  final _formkey = GlobalKey<FormState>();
  final List<String> categories = ["Spor", "Vasıta", "Elektronik"];

  editStuff(stuffID) {
    final FirebaseAuth auth = FirebaseAuth.instance;
    final User? user = auth.currentUser;
    final _uid = user!.uid;
    FirebaseFirestore.instance.collection('Stuffs').doc(stuffID).update({
      'title': _currentTitle,
      'details': _currentDetails,
      'price': _currentPrice,
      'category': _currentCategory,
      'userID': _uid
    });
  }

  bool validatePrice(String str) {
    RegExp _numeric = RegExp(r'^-?[0-9] $');
    return _numeric.hasMatch(str);
  }

  //form values
  String? _currentTitle;
  String? _currentDetails;
  String? _currentPrice;
  String? _currentCategory;

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formkey,
      child: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            Text(
              'Edit your stuff',
              style: TextStyle(fontSize: 18.0),
            ),
            SizedBox(height: 20.0),
            TextFormField(
              decoration: InputDecoration(
                  fillColor: Colors.brown, hintText: 'Title', filled: true),
              validator: (val) {
                if ((validatePrice(val!) == false)) {
                  return "Please enter a number";
                }
                if (val.isEmpty == true) {
                  return "Please enter a value";
                }
                return null;
              },
              onChanged: (val) => setState(() => _currentTitle = val),
            ),
            SizedBox(height: 20.0),
            TextFormField(
              keyboardType: TextInputType.multiline,
              minLines: 1, //Normal textInputField will be displayed
              maxLines: 5,
              decoration: InputDecoration(
                  fillColor: Colors.brown, hintText: 'Details', filled: true),
              validator: (val) =>
                  val!.isEmpty ? 'Please add a detail' : null,
              onChanged: (val) => setState(() => _currentDetails = val),
            ),
            SizedBox(height: 20.0),
            TextFormField(
              decoration: InputDecoration(
                  fillColor: Colors.brown, hintText: 'Price', filled: true),
              validator: (val) =>
                  val!.isEmpty ? 'Please enter a price' : null,
              onChanged: (val) => setState(() => _currentPrice = val),
            ),
            SizedBox(height: 20.0),
            DropdownButtonFormField(
              items: categories.map((category) {
                return DropdownMenuItem(
                  value: category,
                  child: Text('$category'),
                );
              }).toList(),
              onChanged: (val) =>
                  setState(() => _currentCategory = val as String?),
            ),
            ElevatedButton(
              style: ElevatedButton.styleFrom(
                primary: Colors.pink[400],
              ),
              child: Text('Ekle', style: TextStyle(color: Colors.white)),
              onPressed: () async {
                editStuff(widget.stuffID);
              },
            ),
          ],
        ),
      ),
    );
  }
}

CodePudding user response:

With the information about screens provided, I can see that your profile_sheet.dart is not having MaterialApp() as the first ancestor. So in place of Material(), use MaterialApp().

Inside build method of profile_sheet.dart, replace Material() to:

    return MaterialApp()
  • Related