Obscuritas
Obscuritas

Reputation: 59

type 'Null' is not a subtype of type 'Icon'

after trying to add an icon to my list tile I constantly get this error:

════════ Exception caught by widgets library ═══════════════════════════════════
The following _TypeError was thrown building Alertbox(dirty, state: _AlertboxState#08465):
type 'Null' is not a subtype of type 'Icon'

The relevant error-causing widget was
Alertbox
lib/screens/team_screen.dart:58
When the exception was thrown, this was the stack
#0      _AlertboxState.build
package:trainings_app/widgets/alertbox_widget.dart:76
#1      StatefulElement.build
package:flutter/…/widgets/framework.dart:4691
#2      ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4574
#3      StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:4746
#4      Element.rebuild
package:flutter/…/widgets/framework.dart:4267
...
════════════════════════════════════════════════════════════════════════════════

Here are the classes referenced by the error: team_screen

  void newTeam() {
    showDialog<Alertbox>(
      context: context,
      builder: (BuildContext context) {
        return Alertbox('Namen auswählen:', addTeam);
      },
    );
  }

alertbox_widget: the error gets caused by "onSubmitted" inside the TextField

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:trainings_app/config/palette.dart';

class Alertbox extends StatefulWidget {
  final String title;
  final Function(String, Icon) parseText;
  const Alertbox(this.title, this.parseText);

  @override
  _AlertboxState createState() => _AlertboxState(title, parseText);
}

class _AlertboxState extends State<Alertbox> {
  final String title;
  final Function(String, Icon) parseText;
  final textController = TextEditingController();

  _AlertboxState(this.title, this.parseText);

  var iconChoice;
  List icons = [
    Icons.sports_volleyball_outlined,
    Icons.sports_handball_outlined,
    Icons.sports_baseball_outlined,
  ];

  @override
  void dispose() {
    textController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Dialog(
      backgroundColor: Colors.transparent,
      elevation: 0,
      insetPadding: EdgeInsets.all(10),
      child: Center(
        child: Container(
          decoration: new BoxDecoration(
            borderRadius: new BorderRadius.all(const Radius.circular(20)),
            color: Colors.white,
          ),
          padding: const EdgeInsets.all(16.0),
          child: SizedBox(
            height: 100,
            child: Column(
              children: [
                Text(
                  title,
                  style: TextStyle(
                    fontSize: 18,
                  ),
                ),
                Row(
                  children: [
                    DropdownButton(
                      value: iconChoice,
                      onChanged: (newIcon) {
                        setState(() {
                          iconChoice = newIcon;
                        });
                      },
                      items: icons.map((icon) {
                        return DropdownMenuItem(
                          value: icon,
                          child: Icon(icon),
                        );
                      }).toList(),
                    ),
                    SizedBox(width: 12),
                    Expanded(
                      child: TextField(
                        onSubmitted: parseText(textController.text, iconChoice),
                        autofocus: true,
                        textAlign: TextAlign.center,
                        controller: textController,
                      ),
                    ),
                    SizedBox(width: 12),
                    ElevatedButton(
                      onPressed: () {
                        parseText(textController.text, iconChoice);
                      },
                      child: const Icon(CupertinoIcons.checkmark),
                      style: ButtonStyle(
                        backgroundColor:
                            MaterialStateProperty.all(Palette.orange),
                      ),
                    ),
                    SizedBox(width: 8),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

I hope anyone can help me or has some kind of solution/work-a-round that can help fix that problem

Upvotes: 0

Views: 592

Answers (1)

novas1r1
novas1r1

Reputation: 1934

So it took me a while to figure out whats the problem, but I think I got it.

I don't know exactly your planned functionality - for e.g. when the fields are empty (text and/or icon), are you doing any validation? You should probably catch that with deactivating the button or displaying an error message. But apart from that:

// method which is called when clicking the submit button
addTeam(String text, Icon icon) {
  // do whatever you do in here
  log('$text $icon');
}
class Alertbox extends StatefulWidget {
  // you dont need to pass the title to the state, you can access it via 
  // widget.title, same for the onParseText method
  final String title;
  final Function(String, Icon) onParseText;

  const Alertbox(this.title, this.onParseText);

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

class _AlertboxState extends State<Alertbox> {
  final textController = TextEditingController();

  // you somehow messed up Icon and IconData, try to define which type it is
  // it can be null since there is no default icon set
  Icon? iconChoice;

  // also define the type for the list
  List<Icon> icons = [
    Icon(Icons.sports_volleyball_outlined),
    Icon(Icons.sports_handball_outlined),
    Icon(Icons.sports_baseball_outlined),
  ];

  @override
  void dispose() {
    textController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Dialog(
      backgroundColor: Colors.transparent,
      elevation: 0,
      insetPadding: EdgeInsets.all(10),
      child: Center(
        child: Container(
          decoration: new BoxDecoration(
            borderRadius: new BorderRadius.all(const Radius.circular(20)),
            color: Colors.white,
          ),
          padding: const EdgeInsets.all(16.0),
          child: SizedBox(
            height: 100,
            child: Column(
              children: [
                Text(
                  widget.title,
                  style: TextStyle(
                    fontSize: 18,
                  ),
                ),
                Row(
                  children: [
                    // you can define the value type of the Dropdown, set it 
                    // to Icon
                    DropdownButton<Icon>(
                      value: iconChoice,
                      onChanged: (newIcon) {
                        setState(() {
                          iconChoice = newIcon;
                        });
                      },
                      items: icons.map((icon) {
                        return DropdownMenuItem(
                          value: icon,
                          child: icon,
                        );
                      }).toList(),
                    ),
                    SizedBox(width: 12),
                    Expanded(
                      child: TextField(
                        onSubmitted: (text) {
                          // this is what causes the error.
                          // you have to check if iconChoice is null
                          // I'm not really sure why you use onSubmitted 
                          // here since you already have the submitbutton?
                          if (iconChoice != null) {
                            widget.onParseText(text, iconChoice!);
                          }
                        },
                        autofocus: true,
                        textAlign: TextAlign.center,
                        controller: textController,
                      ),
                    ),
                    SizedBox(width: 12),
                    ElevatedButton(
                      onPressed: () {
                        // you need to make sure iconChoice is not null
                        // before calling that method. Use some kind of 
                        // validation here, like mentioned above
                        widget.onParseText(textController.text, 
                        iconChoice!);
                      },
                      child: const Icon(CupertinoIcons.checkmark),
                      style: ButtonStyle(
                        backgroundColor:
                            MaterialStateProperty.all(Colors.orange),
                      ),
                    ),
                    SizedBox(width: 8),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Upvotes: 1

Related Questions