Home > Software engineering >  How to Enable button on success http request Flutter
How to Enable button on success http request Flutter

Time:04-16

Does anybody know how to enable a Flutter ElevatedButton on response status 200.

I have post method for fetching data in sevices.dart

Future<http.Response> postRequest() async {
  var data = await formatJsonData() as Map<String, dynamic>;
  var body = json.encode(data);
  var response = await http.post(
      Uri.parse('https://link.com'),
      headers: {
        'Content-Type': 'application/json',
      },
      body: body);

  if (response.statusCode == 200) {
    return response;
  } else {
    throw Exception('Failed to create processing.');
  }
}

There is page where i need to enable button and call method resetVariables()

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

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

class _FinalPageState extends State<FinalPage> {

  void resetVariables() {
    processingName = '';
    processingQuantity = null;
    linkID = '';
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('SLV'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Column(
              children: <Widget>[      
                ElevatedButton(           
                    onPressed: () {
                      resetVariables();
                      Navigator.pushReplacement(
                        context,
                        MaterialPageRoute(
                            builder: (context) => const Scanner()),
                      );
                    },
                    child: const Text('Done'))
              ],
            )
          ],
        ),
      ),
    );
  }  
}

What is the best solution to do this?

CodePudding user response:

First you need implement a way to enable or disable the button. That can be done by adding a property

bool enabled = false;

to the State and changing the onPressed attribute of ElevatedButton:

onPressed: enabled ? () {
  resetVariables();
    Navigator.pushReplacement(
      context,
      MaterialPageRoute(
        builder: (context) => const Scanner()),
    );
} : null,

onPressed being null will disable the button.

Now we need a way to access the State from whereever you're using your request method. We need to do two things to achieve this.

We need to change the State to not be private anymore by replacing _FinalPageState with FinalPageState everywhere (the underscore makes the state private).

We need to find the State by giving it a GlobalKey. Create a key somewhere, where it can be accessed from your service, as well as when building your Widget:

final GlobalKey<FinalPageState> finalPageKey = GlobalKey();

When building your final page use that key (if you have multiple FinalPage widgets be sure to give each one a different key)

FinalPage(finalPageKey);

Now you can use that key to access the State when making your request:

try {    
  http.Response response = await postRequest();
  finalPageKey.currentState?.setState(() {
    enabled = true;
  });
} catch (e) {
  //handle exceptions
}

CodePudding user response:

You could create, a cubit for that post method, and use blocbuilder with build when: parameter awaiting the success state.

Another quick but dirty solution would be to use future builder that has button lookalike (made in simple container) and when post function finishes it returns your elevated button.

Still the cubit solution would be the best approach. Here you can learn more about proper state management and ui rebuild control with blocs and cubits.

  • Related