Home > database >  Flutter Stepper widget - conditionally hide a step
Flutter Stepper widget - conditionally hide a step

Time:01-09

I am trying to display the step 1 only if the api call returns true on the first step.

Stepper(
          currentStep: _currentStepper,
          onStepContinue: _continueStep,
          steps: [
            Step(
              title: const Text('Let\'s start with your phone number'),
              ***// call api***
            ),
            Step(***// this step should be displayed only if the first step returns true***
                title: const Text(
                    'Please enter the code sent to your mobile device'),
                content: OTP CODE Step
          ],
        ),


  void _continueStep() {
    if (_currentStepper == 0) {
      if (_formKey.currentState!.validate()) {
        _signUpUser();
        _currentStepper = 1;
      }
    }
  }

CodePudding user response:

Note: this isn't a tailored solution, you'll have to adapt this example to fit your needs.

The problem

Usually, to show/hide widgets, you would use the enter image description here

Create a list of steps, and add another widget based on a condition:

 final _steps = [
    Step(title: Text("step 1"), content: Text("content 1")),
    Step(title: Text("step 2"), content: Text("content 2")),
  ];

and within the Stepper widget:

 steps: isVisible
              ? [
                  ..._steps,
                  Step(title: Text("step 3"), content: Text("content 3"))
                ]
              : _steps,

Also, use a random key for the Stepper widget, otherwise, you'll receive an error.

Complete example:

import 'dart:math';

import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: const Scaffold(
        body: Center(
          child: Test(),
        ),
      ),
    );
  }
}

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

  @override
  State<Test> createState() => _TestState();
}

class _TestState extends State<Test> {
  var isVisible = false;
  final _steps = [
    const Step(title: Text("step 1"), content: Text("content 1")),
    const Step(title: Text("step 2"), content: Text("content 1")),
  ];
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextButton(
            onPressed: () {
              setState(() {
                isVisible = !isVisible;
              });
            },
            child: const Text("toggle the third step")),
        // show the steps
        Stepper(
          // use a random key
          key: Key(Random.secure().nextDouble().toString()),
          // i want to show 2 steps, but if the `isVisible` is true, i want to show 3 steps
          steps: isVisible
              ? [
                  ..._steps,
                  const Step(title: Text("step 3"), content: Text("content 3"))
                ]
              : _steps,
          currentStep: 0,
          onStepContinue: () {},
          onStepCancel: () {},
        ),
      ],
    );
  }
}

CodePudding user response:

I don't know if you plan to call a Rest API service in Presentation Layer, I think it's not correct, the best solution for this scenario is to use the BLOC pattern.

  • Related