Search code examples
androidfluttermodelmulti-levelexpandable

The argument type 'Widget Function(Categoria)' can't be assigned to the parameter type 'dynamic Function(Child)'. (Model) Flutter


I am following this example.

https://esflutter.dev/docs/catalog/samples/expansion-tile-sample

to make an expandable of multi levels in the categories. I have a tree of up to 3 categories.

but it gives me this error: I put it in the image so it can be seen in which part is marking the error:

enter image description here

As I am relatively new, I have been trying to solve it for days but I do not realize that it could be, I also leave my model below because I think that there is the error, maybe there is some way other than .map? or I do not realize the solution, please if someone could help me.

// To parse this JSON data, do
//
//     final categorias = categoriasFromJson(jsonString);

import 'dart:convert';

Categorias categoriasFromJson(String str) => Categorias.fromJson(json.decode(str));

String categoriasToJson(Categorias data) => json.encode(data.toJson());

class Categorias {
    Categorias({
        this.res,
        this.id,
        this.empresa,
        this.idioma,
        this.categorias,
    });

    int res;
    int id;
    int empresa;
    String idioma;
    List<Categoria> categorias;

    factory Categorias.fromJson(Map<String, dynamic> json) => Categorias(
        res: json["res"],
        id: json["id"],
        empresa: json["empresa"],
        idioma: json["idioma"],
        categorias: List<Categoria>.from(json["categorias"].map((x) => Categoria.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "res": res,
        "id": id,
        "empresa": empresa,
        "idioma": idioma,
        "categorias": List<dynamic>.from(categorias.map((x) => x.toJson())),
    };
}

class Child {
    Child({
        this.id,
        this.name,
        this.img,
        this.titulo,
        this.children,
        this.baos,
    });

    int id;
    String name;
    String img;
    int titulo;
    List<Categoria> children;
    String baos;

    factory Child.fromJson(Map<String, dynamic> json) => Child(
        id: json["id"],
        name: json["name"] == null ? null : json["name"],
        img: json["img"],
        titulo: json["titulo"],
        children: json["children"] == null ? null : List<Categoria>.from(json["children"].map((x) => Categoria.fromJson(x))),
        baos: json["Baños"] == null ? null : json["Baños"],
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "name": name == null ? null : name,
        "img": imgValues.reverse[img],
        "titulo": titulo,
        "children": children == null ? null : List<dynamic>.from(children.map((x) => x.toJson())),
        "Baños": baos == null ? null : baos,
    };
}

class Categoria {
    Categoria({
        this.id,
        this.name,
        this.img,
        this.titulo,
        this.children,
    });

    int id;
    String name;
    String img;
    int titulo;
    List<Child> children;

    factory Categoria.fromJson(Map<String, dynamic> json) => Categoria(
        id: json["id"],
        name: json["name"],
        img: json["img"],
        titulo: json["titulo"],
        children: json["children"] == null ? null : List<Child>.from(json["children"].map((x) => Child.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "name": name,
        "img": imgValues.reverse[img],
        "titulo": titulo,
        "children": children == null ? null : List<dynamic>.from(children.map((x) => x.toJson())),
    };
}

enum Img { FOTOSCIRCULOS_INSECTICIDA_PNG, EMPTY }

final imgValues = EnumValues({
    "": Img.EMPTY,
    "fotoscirculos/insecticida.png": Img.FOTOSCIRCULOS_INSECTICIDA_PNG
});

class EnumValues<T> {
    Map<String, T> map;
    Map<T, String> reverseMap;

    EnumValues(this.map);

    Map<T, String> get reverse {
        if (reverseMap == null) {
            reverseMap = map.map((k, v) => new MapEntry(v, k));
        }
        return reverseMap;
    }
}

EntryItem class:

class BuyView extends StatefulWidget {
  final List<Categoria> categorias;

  const BuyView({Key key, this.categorias}) : super(key: key);

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

class _BuyViewState extends State<BuyView> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('ExpansionTile'),
        ),
        body: ListView.builder(
          itemBuilder: (BuildContext context, int index) =>
              EntryItem(widget.categorias[index]),
          itemCount: widget.categorias.length,
        ),
      ),
    );
  }
}
// Displays one Entry. If the entry has children then it's displayed
// with an ExpansionTile.
class EntryItem extends StatelessWidget {
  const EntryItem(this.entry);

  final Categoria entry;

  Widget _buildTiles(Categoria root) {
    if (root.children.isEmpty) return ListTile(title: Text(root.name));
    return ExpansionTile(
      key: PageStorageKey<Categoria>(root),
      title: Text(root.name),
      children: root.children.map(_buildTiles).toList(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return _buildTiles(entry);
  }
}

Solution

  • It seems that your Categoria and Child model share almost all of their attributes. The issue is that the _buildTiles expects a Categoria and the children of Categoria are Child.

    If you merge the Child and Categoria models you can do as follows.

    class EntryItem extends StatelessWidget {
      const EntryItem(this.entry);
    
      final Categoria entry;
    
      Widget _buildTiles(Categoria root) {
        if (root.children.isEmpty) return ListTile(title: Text(root.name));
        return ExpansionTile(
          key: PageStorageKey<Categoria>(root),
          title: Text(root.name),
          children: root.children.map((e)=>_buildTiles(e)).toList(),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return _buildTiles(entry);
      }
    }
    
    void main() {
      runApp(ExpansionTileSample());
    }
    
    
    class Categoria {
      Categoria({
        this.id,
        this.name,
        this.img,
        this.titulo,
        this.children,
        this.baos,
      });
    
      int id;
      String name;
      String img;
      int titulo;
      List<Categoria> children;
      String baos;
    
      factory Categoria.fromJson(Map<String, dynamic> json) => Categoria(
        id: json["id"],
        name: json["name"] == null ? null : json["name"],
        img: json["img"],
        titulo: json["titulo"],
        children: json["children"] == null ? null : List<Categoria>.from(json["children"].map((x) => Categoria.fromJson(x))),
        baos: json["Baños"] == null ? null : json["Baños"],
      );
    
      Map<String, dynamic> toJson() => {
        "id": id,
        "name": name == null ? null : name,
        "img": imgValues.reverse[img],
        "titulo": titulo,
        "children": children == null ? null : List<dynamic>.from(children.map((x) => x.toJson())),
        "Baños": baos == null ? null : baos,
      };
    }
    
    
    
    enum Img { FOTOSCIRCULOS_INSECTICIDA_PNG, EMPTY }
    
    final imgValues = EnumValues({
      "": Img.EMPTY,
      "fotoscirculos/insecticida.png": Img.FOTOSCIRCULOS_INSECTICIDA_PNG
    });
    
    class EnumValues<T> {
      Map<String, T> map;
      Map<T, String> reverseMap;
    
      EnumValues(this.map);
    
      Map<T, String> get reverse {
        if (reverseMap == null) {
          reverseMap = map.map((k, v) => new MapEntry(v, k));
        }
        return reverseMap;
      }
    }