Home > Software design >  Flutter Riverpod for local and global variables
Flutter Riverpod for local and global variables

Time:02-05

i have two text editing controllers, im trying to give those text editing controllers initial values fetched from the api. I need to declare the text editing controllers globaly and give the initial value from the api, so what i need is to use data3.firstName and data3.lastName to the global variables, if i try declaring the variables and the function inside build it doesnt work, so just need to use the fetched data to global text editing controllers so i can give initial values.

late Future<Response> futureData;

  @override
  void initState() {
    super.initState();
    futureData = fetchAccountData();
  }

  final _formKey = GlobalKey<FormState>();

  TextEditingController editedFirstName =
      TextEditingController(text: 'Hello'); // needs to be data3.firsName
  TextEditingController editedLastName = TextEditingController(text: 'Riverpod looks great');// needs to be data3.lastName

  Future<void> putAccountData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String? authorization = prefs.getString('authorization');
    var url = 'https://dev.api.wurk.skyver.co/api/v1/employees/account';
    Map payload = {
      "firstName": editedFirstName.text,
      "lastName": editedLastName.text,
    };
    try {
      final response = await http.put(Uri.parse(url),
          headers: <String, String>{
            'authorization': authorization ?? basicAuth.toString(),
            "Content-Type": "application/json"
          },
          body: jsonEncode(payload));
    } catch (er) {}
  }

  @override
  Widget build(BuildContext context) {
    var height = MediaQuery.of(context).size.height;
    var width = MediaQuery.of(context).size.width;

    return SafeArea(
      child: WillPopScope(
        onWillPop: () async {
          Navigator.pushReplacement(
            context,
            MaterialPageRoute(
              builder: (context) => const ProfileScreen(),
            ),
          );
          return shouldPop;
        },
        child: KeyboardDismisser(
          gestures: const [
            GestureType.onTap,
            GestureType.onPanUpdateDownDirection
          ],
          child: Form(
            key: _formKey,
            child: Scaffold(
                resizeToAvoidBottomInset: false,
                appBar: AppBar(
                  backgroundColor: Colors.blue,
                  title: const Text(
                    'Edit My Profile',
                    style: TextStyle(
                        color: Colors.white, fontWeight: FontWeight.bold),
                  ),
                  leading: IconButton(
                    icon: const Icon(Icons.arrow_back),
                    onPressed: () {
                      Navigator.pushReplacement(
                        context,
                        MaterialPageRoute(
                          builder: (context) => const ProfileScreen(),
                        ),
                      );
                    },
                  ),
                ),
                body: FutureBuilder<Response>(
                  future: futureData,
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      AccountData data3 = AccountData.fromJson(
                        json.decode(snapshot.data!.body),
                      );

                      return Column(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: [
                          Container(
                            width: width,
                            height: height / 1.9,
                            decoration: BoxDecoration(
                              border: Border.all(
                                color: Colors.black,
                                width: 3,
                              ),
                            ),
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                              children: [
                                Row(
                                  children: [
                                    const Padding(
                                      padding: EdgeInsets.all(30),
                                      child: Text(
                                        "First Name:",
                                        style: TextStyle(
                                            fontSize: 20,
                                            fontWeight: FontWeight.bold),
                                      ),
                                    ),
                                    const Spacer(),
                                    Padding(
                                      padding: const EdgeInsets.all(30),
                                      child: SizedBox(
                                        width: width / 2.5,
                                        child: Center(
                                          child: TextFormField(
                                            textAlignVertical:
                                                TextAlignVertical.center,
                                            //initialValue: editedFirstName.text = data3.firstName,
                                            controller: editedFirstName,
                                            // ..selection =
                                            //     TextSelection.collapsed(
                                            //         offset: data3
                                            //             .firstName.length),
                                            decoration: InputDecoration(
                                              contentPadding:
                                                  const EdgeInsets.symmetric(
                                                      vertical: 10.0,
                                                      horizontal: 10.0),
                                              border: OutlineInputBorder(
                                                borderRadius:
                                                    BorderRadius.circular(10),
                                                borderSide: const BorderSide(
                                                    color: Colors.red,
                                                    width: 1),
                                              ),
                                            ),
                                            style: const TextStyle(
                                              fontSize: 17,
                                              fontWeight: FontWeight.bold,
                                            ),
                                            // inputFormatters: [
                                            //   LengthLimitingTextInputFormatter(15)
                                            // ],
                                            validator: (value) {
                                              if (value == null ||
                                                  value.isEmpty) {
                                                return 'Name is required';
                                              }
                                              return null;
                                            },
                                          ),
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                                Row(
                                  children: [
                                    const Padding(
                                      padding: EdgeInsets.all(30),
                                      child: Text(
                                        'Last Name:',
                                        style: TextStyle(
                                          fontSize: 20,
                                          fontWeight: FontWeight.bold,
                                        ),
                                      ),
                                    ),
                                    const Spacer(),
                                    Padding(
                                      padding: const EdgeInsets.all(30),
                                      child: SizedBox(
                                        width: width / 2.5,
                                        child: TextFormField(
                                          //initialValue: editedLastName.text = data3.lastName,
                                          controller: editedLastName,
                                          // ..selection =
                                          //     TextSelection.collapsed(
                                          //         offset:
                                          //             data3.lastName.length),
                                          decoration: InputDecoration(
                                            contentPadding:
                                                const EdgeInsets.symmetric(
                                                    vertical: 10.0,
                                                    horizontal: 10.0),
                                            border: OutlineInputBorder(
                                              borderRadius:
                                                  BorderRadius.circular(10),
                                            ),
                                          ),
                                          style: const TextStyle(
                                              fontSize: 17,
                                              fontWeight: FontWeight.bold),
                                        ),
                                      ),
                                    ),
                                  ],
                                ),

CodePudding user response:

Looks like you want to provide an initial value to TextField, but the value is async fetched from the server.

You are on the right track to use a TextEditingController, but since you won't have the value ready at first, you should not use TextEditingController(text: 'Hello') when creating the controller.

Instead, you can create a controller without a default value, for example: final _controller = TextEditingController(). And then after you got the data, say after calling fetchAccountData() method in initState, you can assign the data to the controller using _controller.text = fetchedValue.

I see you are also using FutureBuilder. Depending on what you want to display before the "default values" are loaded, you might or might not need the FutureBuilder anymore.

Quick demo:

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

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

class _QuickDemoState extends State<QuickDemo> {
  final _controller = TextEditingController();

  @override
  void initState() {
    super.initState();
    _fetchData();
  }

  _fetchData() async {
    // do your network call here
    await Future.delayed(const Duration(seconds: 1));
    // and then parse your response here
    final data = 'Hello';
    // eventually you will have data, so assign it:
    _controller.text = data;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: TextField(
          controller: _controller,
        ),
      ),
    );
  }
}
  •  Tags:  
  • Related