How can I update my initialValue of TextFormField by setState() which is not happening?

Viewed 33

This is my settings.dart

import 'package:flutter/material.dart';
import 'package:upm/file_manager.dart';
import 'package:upm/screens/home.dart';
import 'package:upm/screens/login.dart';
import 'package:upm/screens/signup.dart';

class Settings extends StatefulWidget {
  static const FileStorage storage = FileStorage();
  const Settings({Key? key}) : super(key: key);

  @override
  State<Settings> createState() => _SettingsState();
}

class _SettingsState extends State<Settings> {
  late Map<String, dynamic> config;

  @override
  void initState() {
    super.initState();
    config = {};
    getData().then((value) {
      setState(() {
        config = value;
      });
    });
  }

  Future<Map<String, dynamic>> getData() async {
    config = await const FileStorage().readConfig();
    print("Ye lo config ${config["serverIP"]}");
    return config;
  }

  @override
  Widget build(BuildContext context) {
    const String name = "Settings";
    return Scaffold(
      appBar: AppBar(
        title: const Text(name),
      ),
      body: Container(
        padding:
            const EdgeInsets.only(left: 15, right: 15, bottom: 15, top: 15),
        child: Center(
          child: Column(
            children: [
              TextFormField(
                initialValue: config["serverIP"].toString(),
                decoration: const InputDecoration(
                  labelText: 'Server IP',
                  border: OutlineInputBorder(),
                ),
              ),
              const SizedBox(
                height: 15,
              ),
              const TextField(
                decoration: InputDecoration(
                  labelText: 'Server Port',
                  border: OutlineInputBorder(),
                ),
              ),
              const SizedBox(
                height: 25,
              ),
              const ElevatedButton(
                onPressed: null,
                child: Text("Save"),
              )
            ],
          ),
        ),
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            ListTile(
              title: const Text('Home'),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => const Home()),
                );
              },
            ),
            ListTile(
              title: const Text('Sign In'),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => const Login()),
                );
              },
            ),
            ListTile(
              title: const Text('Sign Up'),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => const Signup()),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

This is my file_manager.dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:path_provider/path_provider.dart';

class FileStorage extends StatelessWidget {
  const FileStorage({Key? key}) : super(key: key);
  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();

    return directory.path;
  }

  Future<File> get _localFileConfig async {
    final path = await _localPath;

    if (await File("$path/config.ini").exists() == false) {
      File("$path/config.ini").create();

      Map<String, dynamic> config = {
        "serverIP": "0.0.0.0",
        "port": 1234,
      };
      writeConfig(config);
    }
    File file = File("$path/config.ini");
    return file;
  }

  Future<Map<String, dynamic>> readConfig() async {
    try {
      final file = await _localFileConfig;
      String temp = await file.readAsString();
      Map<String, dynamic> contents = await jsonDecode(temp);
      print("Ye Lo contents $contents");

      return contents;
    } catch (e) {
      print("Ye bhi Parh Lo-T $e -T");
      return <String, dynamic>{};
    }
  }

  Future<File> writeConfig(Map<String, dynamic> config) async {
    final file = await _localFileConfig;

    return file.writeAsString(json.encode(config));
  }

  @override
  Widget build(BuildContext context) {
    throw UnimplementedError();
  }
}

I am trying to fetch a json map from a local file and using one of it keys and values as a variable for my initialValue in settings.dart. The problem I am facing is that after building all the widgets it does not rebuild my TextFormField widget with the new value of the config variable and the initialValue shows "null" and does not update.

1 Answers

You will be only able to set initial value 1st time, after that it won't response by default. It would be better to use TextEditingController instead.

Declare a variable on state class.

 TextEditingController controller =
      TextEditingController.fromValue(TextEditingValue(text: "initValue"));

 @override
  void initState() {
    super.initState();
    config = {};
    getData().then((value) {
        controller.text = value; // controller doent need setState to update
       
    });
  }

And use the controller

  TextFormField(
    controller: controller,
  )
Related