Search code examples
flutterdartflutter-widget

How can Widget Classes Arguments be used as props to create dynamic Widgets with Row and Columns in Flutter?


I am revisiting Flutter development after working with React after some times and I was trying to implement something as passing props across multiple components, in order to create dynamic Widgets (components) that render based on props. I could somehow achieve the result but still I cannot understand something.

So, in this example, I am creating a Widget Class which accepts text as an argument, and I am able to use the value of the text below in the Text return method:


class NeoText extends StatelessWidget {
  final String text;

  const NeoText({ 
    super. Key,
    required this.text,
  });

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: const TextStyle(
        color: Colors.white,
        fontSize: 15.0,
        fontWeight: FontWeight.bold,
        letterSpacing: 1.0,
        fontFamily: 'Lato',
      ),
    );
  }
}

And I can use the Widget (component) that I created in my main.dart file like:

...
...
    child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: const [
                  NeoText(
                    text: "⚽️Goals: 2",
                  ),
                  NeoText(
                    text: "🅰️Assists: 6",
                  ),
                  NeoText(
                    text: "🧤Saves: 26",
                  ),
                ],
              ),
...
...

But when I want to create a more complex Custom Widget that accepts multiple childs and other arguments I cannot seem to make it work.

Here is an example. I am creating this CustomCard widget which can have multiple widgets in its structure, including a Text widget. Now here I am doing the same thing, I am creating a variable named title, and trying to pass it in the Text Widget, so when I use this component in my main.dart file I can provide the title name and make the Card different from other cards. But on return method of Text I get an error (attached after the code below):

import 'package:flutter/material.dart';

class CustomCard extends StatelessWidget {
  final String? title;

  const CustomCard({super.key, @required this.title});

  @override
  Widget build(BuildContext context) {
    // Material is a conceptual piece
    // of paper on which the UI appears.
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(3.0),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
            Icon(
              Icons.sports_soccer,
              color: Colors.black,
              size: 50.0,
            ),
            SizedBox(
              height: 8.0,
            ),
            Text(
              title!,
              style: TextStyle(
                color: Colors.black,
                fontSize: 15.0,
                fontWeight: FontWeight.bold,
                letterSpacing: 1.0,
                fontFamily: 'Lato',
              ),
            ),
            SizedBox(
              height: 8.0,
            ),
            Text(
              '26',
              style: TextStyle(
                color: Colors.black,
                fontWeight: FontWeight.bold,
                fontSize: 15.0,
                letterSpacing: 1.0,
                fontFamily: 'Lato',
              ),
            ),
          ],
        ),
      ),
    );
  }
}

I am wondering now, why this is not working considering that the first example works just the way I want.

error screenshot widget props

Another challenge that I am having also is, to render as many children as I provide to my Costum Method. So lets say, I want create my own Custom Widget that accepts a dynamic number of children to render. In other words, we can also say that, I want to create a custom Row component that renders as many children as I provide. Here is an example of what I am trying to achieve is:

I want that in my main I render this kind of Custom Widget, that renders a number of children inside it:

              children: [
                  NeoText(
                    text: "⚽️Goals: 2",
                  ),
                  NeoText(
                    text: "🅰️Assists: 6",
                  ),
                  NeoText(
                    text: "🧤Saves: 26",
                  ),
                ],
              ),
            ),

I want to make the ScoreRow Widget a Custom Widget that accepts multiple children inside it and renders as many children as provided like in the below example. Is it possible to do something like that? Or is there any concept I need to cover?

import 'widgets/neo_text.dart';

class ScoreRow extends StatelessWidget {
  final Widget? children;

  const ScoreRow({super.key, required this.children});

  @override
  Widget build(BuildContext context) {
    return (
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [children!],
          // add the children here
      )
    );
     
  }
}```

Solution

  • Try to remove const keyword

     Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
    

    this:

    Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
    

    In order to have a widget that is compile-time constant, all of its properties should also be compile-time constants.