66

I try to create some custom widgets with some parameters in the constructor. This widget has some optional and required parameters.

how can make Function type parameter optional in my Widget.

class TextInputWithIcon extends StatefulWidget {
  final String iconPath;
  final String placeHolder;
  final Function(bool) onFocusChange;
  const TextInputWithIcon(
      {Key key,
      @required this.iconPath,
      this.placeHolder = "",
      this.onFocusChange})
      : super(key: key);

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

class _TextInputWithIconState extends State<TextInputWithIcon> {
@override
  Widget build(BuildContext context) {
    return MY_WIDGET;
   }
}
7
  • What error do you get? Is it static or at runtime? Commented Jan 30, 2019 at 15:55
  • @GünterZöchbauer. if function not set The method 'call' was called on null. Commented Jan 30, 2019 at 15:57
  • That's not about the parameter being optional, that's about when no function is passed to that parameter, then of course you can't call it. Can you please explain what the expected behavior is? Commented Jan 30, 2019 at 15:58
  • I try to get focus change in 'TextField' on parent widget. but just in some screen focus change does not matter Commented Jan 30, 2019 at 16:02
  • How does the component that it does not matter? Commented Jan 30, 2019 at 16:04

3 Answers 3

126

Optional parameters can be either positional or named, but not both.

Named parameters are optional by default so you don't have to assign the default value.

If a parameter is optional but can’t be null, provide a default value.

With null safety

class TextInputWithIcon extends StatefulWidget {
  final String iconPath;
  final String placeHolder;
  final Function(bool)? onFocusChange; // nullable and optional
  
  const TextInputWithIcon(
      {Key? key,
      required this.iconPath, // non-nullable and required
      this.placeHolder = "", // non-nullable but optional with a default value
      this.onFocusChange, // nullable and optional
      })
      : super(key: key);

  @override
  _TextInputWithIconState createState() => _TextInputWithIconState();

}

Without null safety

const TextInputWithIcon(
      {Key key,
      @required this.iconPath,
      this.placeHolder = "",
      this.onFocusChange
})
      : super(key: key);

Usage:

void _focusChanged(bool value) {

    // using null-aware operator (for both with and without null safety)
    onFocusChange?.call(value);
    
    // or without null-aware operator 
    
    // with null safety
    if(onFocusChange != null) {
      onFocusChange!(value);
    }

    // without null safety
    if(onFocusChange != null) {
      onFocusChange(value);
    }

  }

Dart 2.17 update:

Although it often makes sense to place positional arguments first, named arguments can be placed anywhere in the argument list when it suits your API:

repeat(times: 2, () {
  ...
});

Have a look at Optional Parameters to understand better.

Edit: Thank you Jonah Williams to clarification.

Sign up to request clarification or add additional context in comments.

6 Comments

onFocusChange does not need to be initialized to null.
Is value assignment not required to make named parameters optional?
Named parameters are optional by default
@UmairM need the same solution for Null Safety. Please share any suggestion. Thanks.
@Kamlesh I updated the answer, please me know if I missed anything :)
|
21

Another option if you don't like named parameters (like me :/) is:

function_name (argument1, [argument2]) {
   // statements
}

arguments in brackets are optional.

source

4 Comments

What if i have argument3 and argument4 and i also want the argument3 and argument4 to be optional together with argument2
If you need more arguments, you can add them like: [arg2, arg3, arg4, ...] Then you have to pass the values in the same order since they are not named.
This means you have to pass all of the arguments that are optional you cant parse arg2 and for example arg4 only, right ?
This was a life saver for my function
16

You can use a default value that does nothing:

class TextInputWithIcon extends StatefulWidget {
  final String iconPath;
  final String placeHolder;
  final Function(bool) onFocusChange;
  const TextInputWithIcon(
      {Key key,
      @required this.iconPath,
      this.placeHolder = "",
      this.onFocusChange = _dummyOnFocusChange})
      : assert(onFocusChange != null), super(key: key);

  @override
  _TextInputWithIconState createState() => _TextInputWithIconState();

  static dynamic _dummyOnFocusChange(bool val) {}
}

I created a static named function instead of just a closure as a default value because closures are not const and currently default values need to be const.

I added the assert(...) to ensure that an error is shown when null is passed explicitly.

4 Comments

if my function don't take argument also not return anything it'll be >> (static _dummyOnFocusChange() {} ) is this way correct because i tried and give error at compile time so i tried ( static dynamic _dummyOnFocusChange() {} ) and worked with me. Can you tell me why worked ??
If you need to pass a parameter depends on final Function(bool) onFocusChange. If you don't intend to return anything, use void. dynamic is kind of a wildcard.
for my case I need to pass a custom model. I can't just declare the whole model if null, I need extra info that it's not there
@GünterZöchbauer how can we pass optional params and use them in a custom widget? Kindly suggest. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.