Anoop Thiruonam
Anoop Thiruonam

Reputation: 2872

How to instantiate final variables in Stateless Widget?

I'm trying to assign certain values to some of the properties based on the input value. The value remains the same throughout the widget's life cycle. Therefore I used Stateless widget. But, I can't assign a value for the props from the constructor.

class InOrOut extends StatelessWidget {
  final Condition condition;
  final bool isIconVisible;
  final Color backgroudColor;
  final Color foregrounndColor;

  InOrOut({Key key, this.condition, this.isIconVisible}) : super(key: key) {
    switch (condition) {
      case Condition.IN:
        backgroudColor = Colors.green[100];
        foregrounndColor = Colors.green[100];
        isIconVisible = false
        break;
      case Condition.ABSENT:
        backgroudColor = Colors.grey[300];
        foregrounndColor = Colors.green[100];
        isIconVisible = true;
        break;
      case Condition.OUT:
        backgroudColor = Colors.red[100];
        foregrounndColor = Colors.green[100];
        isIconVisible = false;
        break;
      default:
        backgroudColor = Colors.red[100];
        foregrounndColor = Colors.green[100];
        isIconVisible = false;
    }
  }

The following error comes when trying to assign a value to prop:

'foregrounndColor' can't be used as a setter because it is final. Try finding a different setter, or making 'foregrounndColor' non-final.dart(assignment_to_final)

If I remove final I can't use it inside the Stateless widget.

Finally, should I change to Stateful widget just because of this?

Upvotes: 7

Views: 5241

Answers (2)

maganap
maganap

Reputation: 2904

To keep the widget Stateless, you need to declare the properties as late final and initialize them in the constructor. Example:

class IntroPage extends StatelessWidget {
  IntroPage(
    this.step, {
    Key? key,
  }) : super(key: key) {
    iconData = _getIconData(step);
    title = 'This is title ${step.toString()}';
    body = _getBody(step);
  }

  final IntroStep step;
  late final IconData iconData;
  late final String title;
  late final String body;

  IconData _getIconData(IntroStep step) {
    IconData iconData;
    switch (step) {
      case IntroStep.step1:
        iconData = Icons.share_sharp;
        break;
      case IntroStep.step2:
        iconData = Icons.sailing;
        break;
      case IntroStep.step3:
        iconData = Icons.grid_view_outlined;
        break;
    }
    return iconData;
  }

  @override
  Widget build(BuildContext context) {
  ...

Upvotes: 8

user10539074
user10539074

Reputation:

class InOrOut extends StatelessWidget {
  final Condition condition;
  final bool isIconVisible;
  final Color backgroundColor;
  final Color foregroundColor;

  InOrOut({Key key, this.condition, bool isIconVisible})
      : backgroundColor = condition == Condition.IN
            ? Colors.green[100]
            : condition == Condition.ABSENT ? Colors.grey[300] : condition == Condition.OUT ? Colors.red[100] : Colors.red[100],
        foregroundColor = condition == Condition.IN
            ? Colors.green[100]
            : condition == Condition.ABSENT ? Colors.green[100] : condition == Condition.OUT ? Colors.green[100] : Colors.green[100],
        isIconVisible = condition == Condition.ABSENT,
        super(key: key);
}

so as I don't see the situation in general I'd prefer to have 3-4 separate widgets or use ternary operations inside build() method but obviously not a statefull widget

Upvotes: 1

Related Questions