Flutter 2.0: How to create a model class for firestore snapshot

Viewed 506

How can I construct a flutter class for firestore snapshot for flutter 2.0

I tried something like this:

import 'package:cloud_firestore/cloud_firestore.dart';

class Post {
  final String pid;
  final String description;

  final DocumentReference reference;

  Post.fromMap(Map<String, dynamic> map, this.pid, this.description, {required this.reference})

  Post.fromSnapshot(DocumentSnapshot snapshot)
      : this.fromMap(snapshot.data(), reference: snapshot.reference);

  @override
  String toString() => "Post<$pid:$description>";
}

But there is an error saying 3 positional arguments expected but 1 found.

3 Answers

The error 3 positional arguments expected but 1 found is there because in your Post.fromMap there are three arguments (snapshot, pid, description) that are required to call this. There is also a 4th one (reference) that is marked required.
But when you are calling this in fromSnapshot, you are only giving two parameters when the required are four.

This is the most common way to define a model.
You can create other member functions as required.

DocumentReference reference field should be nullable in my opinion in case data is not from firebase.

class Post {
  final String pid;
  final String description;

  final DocumentReference? reference;

  Post({
    required this.pid,
    required this.description,
    required this.reference,
  });

  factory Post.fromMap(Map<String, dynamic> map, {required DocumentReference? reference}) {
    return Post(
        pid: map['pid'], 
        description: map['description'],
        reference: reference,
    );
  }

  factory Post.fromSnapshot(Map<String, dynamic> snapshot) =>
      Post.fromMap(snapshot, reference: snapshot.reference);

  @override
  String toString() => "Post<$pid:$description>";
}

You were not passing pid and description (which were positional parameters). You could either make them optional named parameter or pass them explicitly.

Solution 1 (making parameters optional):

class Post {
  final String pid;
  final String description;
  final DocumentReference reference;

  Post.fromSnapshot(DocumentSnapshot snapshot)
      : this.fromMap(
          snapshot.data() as Map<String, dynamic>,
          reference: snapshot.reference,
        );

  Post.fromMap(
    Map<String, dynamic> map, {
    required this.reference,
    this.pid = 'dummyID',
    this.description = 'dummyDesc',
  });

  @override
  String toString() => 'Post<$pid:$description>';
}

Solution 2 (passing parameters):

class Post {
  final String pid;
  final String description;
  final DocumentReference reference;

  Post.fromSnapshot(DocumentSnapshot snapshot)
      : this.fromMap(
          snapshot.data() as Map<String, dynamic>,
          'pid',
          'description',
          reference: snapshot.reference,
        );

  Post.fromMap(
    Map<String, dynamic> map,
    this.pid,
    this.description, {
    required this.reference,
  });

  @override
  String toString() => 'Post<$pid:$description>';
}

Got it to work like below:

class Post {
  final String pid;
  final String description;
  final DocumentReference reference;

  Post.fromSnapshot(DocumentSnapshot snapshot)
      : this.fromMap(
          snapshot.data() as Map<String, dynamic>,
          reference: snapshot.reference,
        );

  Post.fromMap(
    Map<String, dynamic> map, {
    required this.reference,
  })  : pid = map['pid'],
        description = map['description'];

  @override
  String toString() => 'Post<$pid:$description>';
}
Related