Flutter for Beginners: Positional Parameter vs Named Parameter

Positional parameters are the type of parameter that should match the order so the value can be identified. On the other hand, the Named parameter uses labels to identify their values.

This post is the 5th part of the Flutter for Beginners Series.

In Flutter we can provide parameters when calling a widget. There are two types of parameters, Positional Parameters, and Named Parameters. Here is an example of the parameters in a built-in Flutter widget:

Text(
  "Hello World",
  style: TextStyle(color: Colors.red),
),

In the example above, we provide two parameters, the "Hello World" text, and the style.  As you can see, we're not using a label in the first parameter, but for the second one, we use the style: label. That's because the first parameter is a Positional Parameter and the second one is a Named Parameter.

When creating our custom widget, whether we create a Stateless Widget or a Stateful Widget, we can define both types of parameters in our widget constructor. Let's learn how to do that!

Positional Parameters

Positional Parameters are defined using the order of that parameter list. It is the mandatory parameter type, meaning you must provide the parameter when calling a function or displaying a widget.

When creating a widget, we can specify what parameter that widget accepts by defining the properties and mentioning the property in the constructor.

class MyStatelessWidget extends StatelessWidget {
  const MyStatelessWidget(this.title, {super.key});
  final String title;

  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}

In the above example, we define a positional parameter called title and then use it as a parameter in the Text widget. We can then call the MyStatelessWidget like so:

MyStatelessWidget("My Title")

To use multiple positional parameters, we can add them after the comma.

  const MyStatelessWidget(this.title, this.description, {super.key});
  final String title;
  final String description;

And call it like so:

MyStatelessWidget("My Title", "My Description")

As you can see, the order of the parameters we provide when calling the widget should match the defined parameter list.

💡
Notice the super.key parameter in the widget constructor. In Flutter, super.key refers to the key property inherited from the superclass of a widget. The Key class is an identifier for identifying and differentiating between widgets, allowing Flutter to efficiently update and manage the widget tree.

Named Parameters

To define a named parameter, we use curly braces to wrap it in the constructor.

  const MyStatelessWidget(
    this.title,
    this.description, {
    super.key,
    this.comment,
  });
  final String title;
  final String description;
  final String? comment;

As you can see in the code above, we add a new named parameter called comment. It is placed inside curly braces along with the key. Now, we can call the widget like so:

MyStatelessWidget("My Title", "My Description", comment: "My Comment")

Notice that we use String? instead of String to define the property. It means the property is nullable and the comment parameter is not required. Let's try to remove the ? and see what happens!

The IDE will tell that there is something wrong. The problem happens when we don't provide the comment parameter, meaning it would be null, but the property is non-nullable (because we remove the ?).

There are two ways to resolve this issue. We can make the comment parameter required or we can set a default value, depending on your need. To make it required, just place the required keyword like so:

required this.comment,

If you want to set a default value instead, just set it like this:

this.comment = "",

In the example above we set an empty string as the default value. You can use any string you want. Here is the full code:

import 'package:flutter/material.dart';

class MyStatelessWidget extends StatelessWidget {
  const MyStatelessWidget(
    this.title,
    this.description, {
    super.key,
    this.comment = "",
  });
  final String title;
  final String description;
  final String comment;

  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}

Accessing a Widget Property from The State Class.

As we discuss in the previous part of the series. The StatefulWidget consist of the class itself and a corresponding class that holds the mutable state. The build function of the Stateful Widget is inside that corresponding class. So, if we want to display a widget property (or parameter) we should do that from inside it.

The question is, how to access the widget property from that corresponding class? the answer is easy, here is an example:

class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({super.key, required this.title});
  final String title;

  @override
  State<StatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return Text(widget.title);
  }
}

As you can see in the code above, we access the title property by using widget.title from inside the corresponding state class.

Conclusion

Now, you should understand the difference between Positional Parameters and Named Parameters. Positional Parameters should match the order defined in the widget. Once it is defined, it is required to provide the Positional Parameter.

The Named Parameters use labels to identify the value. The Named Parameters can be set to required or not required (nullable).