juliarobins
juliarobins

Reputation: 11

How to add a value to a map of type Map<String, dynamic>?

This map keeps track of who had upvoted a post and who hasn't. The string stores the userid and the value is a boolean of whether he has upvoted the post or not. I used Map<String, bool> initially but there was an error saying 'InternalLinkedHashMap<String, dynamic> is not a subtype of Map<String, bool>. Hence i changed the value from type bool to dynamic. However, the following code does not seem to work for type dynamic. How do i change the code and initialise the boolean to a false with dynamic type?

@override
  void initState() {
    super.initState();
    Firestore.instance.collection('public').document('internship_experiences').collection('Experiences')
    .document(widget.experience.documentid).get().then((value) async {
      final uid = await Provider.of(context).auth.getCurrentUID();

    if (value.data['saved'] == null
      ||value.data['upvotes'] == null || value.data['saved'][uid] == null || value.data['upvotes'][uid] == null) {

      widget.experience.saved.putIfAbsent(uid, () => false);
      widget.experience.upvotes.putIfAbsent(uid, () => false);

      Firestore.instance.collection('public').document('internship_experiences').collection('Experiences')
      .document(widget.experience.documentid).setData({
        'saved': widget.experience.saved,
        'upvotes': widget.experience.upvotes,
      }, merge: true).then((_){
        print("success at null!");
        });
      } else {
        setState(() {
          isSaved = value.data['saved'][uid]; //accessing value 
          isUpvoted = value.data['upvotes'][uid];
        });
       print('set state upon opening page');
      }
    });
  }


class Experience {
  String title;
  String company; 
  String role;
  String timePeriod; 
  String content; 
  String timestamp;
  String username;
  String profilePicture;
  String documentid;
  String ownerid;
  Map<String, dynamic> saved = {};
  Map<String, dynamic> upvotes = {};
  

  Experience(
    this.title,
    this.timePeriod,
    this.role,
    this.content,
    this.timestamp,
    this.company,
    this.username,
    this.profilePicture,
    this.documentid,
    this.ownerid,
    this.saved,
    this.upvotes,
  );

  Experience.fromSnapshot(DocumentSnapshot snapshot) : 
  title = snapshot["title"],
  content = snapshot['content'],
  timestamp = snapshot['timestamp'],
  role = snapshot['role'],
  username = snapshot['username'],
  profilePicture = snapshot['profilePicture'],
  documentid = snapshot['documentid'],
  timePeriod = snapshot['timePeriod'],
  ownerid = snapshot['ownerid'],
  company = snapshot['company'],
  upvotes = snapshot['upvotes'],
  saved = snapshot['saved'];
}

Upvotes: 1

Views: 4487

Answers (2)

Jack Reilly
Jack Reilly

Reputation: 483

Firstly, you can likely solve your Map<String, bool> problem by wrapping your Map<String,dynamic> value with Map.from. The firestore document data values are stored as Map<String,dynamic> since firestore permits arbitrary values for all maps, and not just booleans. Since you know that all values are booleans (because you enforce the convention in your implicit Firestore schema), you need to make an explicit cast of the Firestore Map<String,dynamic> to Map<String,bool> using Map.from:

import 'dart:convert';

void foo(Map<String,bool> boolMap) {}

void main() {
  // jsonDecode does not return Map<String,bool>, even though all items
  // in the serialized map are bools.
  // Maybe you obtained your map in a similar manner?
  final Map<String,dynamic> dynamicMap = jsonDecode('{"x":true}');
  
  // This line will fail because dynamicMap is not Map<String,bool>
  // foo(dynamicMap);

  // This line succeeds because Map.from will cast the dynamic
  // map to a Map<String,bool> since all types present in the
  // parent map have bool keys.
  // Otherwise, Map.from will fail.
  foo(Map.from(dynamicMap))
}

To answer your second question, your code above should work fine, but you might require an explicit cast of the value of an entry if you have certain strict type-checking options set:

void main() {
  final map = <String,dynamic>{};
  map.putIfAbsent('a', () => true);
  print(map);
  // Here is the explicit cast from dynamic to bool.
  // Obviously, you need to be sure that map['a'] is a bool or this will fail.
  final bool b = map['a'] as bool;
  print(b);
}

Upvotes: 2

towhid
towhid

Reputation: 3278

You are putting a function instead of bool value, that's why the error occurred, Just use (true/false)

widget.experience.upvotes.putIfAbsent(uid, false);

Hope this helps :)

Upvotes: 0

Related Questions