3
\$\begingroup\$

I'm new to coding in general and I am working in flutter right now. I've successfully been able to add single string objects into a list but I'm having issues adding an object with multiple strings into a list. I'd love some guidance if anyone's able to help!

This is my model

import 'dart:convert';

import 'package:json_annotation/json_annotation.dart';

@JsonSerializable(anyMap: true, explicitToJson: true)
class Product {
  String productName;
  String productDescription;

  Product(this.productName, this.productDescription);

  factory Product.fromJson(Map<String, dynamic> json) =>
    _$ProductFromJson(json);
  Map<String, dynamic> toJson() => _$ProductToJson(this);
}

Product _$ProductFromJson(Map<String, dynamic> json) {
  return Product(
    json['product name'] as String,
    json['product description'] as String,
  );
}

Map<String, dynamic> _$ProductToJson(Product instance) => <String, dynamic>{
      'product name': instance.productName,
      'product description': instance.productDescription,
    };

//trying to add Product strings into products
class UserData {
  ...
  final List<dynamic> accommodations; //successfully able to add single strings to list
  final List<dynamic> products; //unable to add multiple string objects to this list
  ...

  UserData(
      {...
      this.accommodations,
      this.products
      ...}
  );

  Map<String, dynamic> toJson() => {"products": this.products};
}

Here is the database function to connect it to firestore

  Future addProduct(List products) async {
    Map<String, dynamic> productMap = {
      'products': products.map((product) => products.toList())
    };
    await userCollection.doc(uid).update(productMap);
  }

The await, which I've edited multiple times, either throws an error "ArgumentError (Invalid argument: Instance of 'Product')" OR "_TypeError (type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, Object>')"

Finally, here is the onPressed event which I'm trying to use to insert the two string values into the products list.

String _currentProductName;
String _currentProductDescription;

these are hooked up to textformfields

onChanged: (val) {
 setState(() => _currentProductName = val);
},
onChanged: (val) {
 setState(() => _currentProductDescription = val);
},

and the onPressed which I've also tried changing multiple times

RaisedButton(onPressed: () async {
 userData.products.add(Product(
  _currentProductName,
  _currentProductDescription));
 await DatabaseService(uid: user.uid).addProduct(userData.products);
}),

Thank you!

\$\endgroup\$
1
  • \$\begingroup\$ What are the objectives of addProduct and ButonPress? They both do similar operations. \$\endgroup\$
    – NirmalCode
    Dec 15, 2021 at 17:30

1 Answer 1

2
\$\begingroup\$
  1. When naming JSON params, use Snail Case:

    json['product_name'] as String,
    json['product_description'] as String,
    
  2. Avoid dynamic as a List Type when you have already declared a Custom type because it can lead to unexpected behaviors in apps.

    Change

    final List<Product> products;
    

    to

    final List<dynamic> products;
    

    Now only Product type objects will be accepted into the products list.

  3. When converting list items into JSON, you need to convert each item to JSON and add them to a list. For this you can use map function.

    Change

    Map<String, dynamic> toJson() => {"products": this.products};
    

    to

    Map<String, dynamic> toJson() => {"products": products.map((e) => e.toJson()).toList()};
    
  4. Based on the code provided, I assume you want to add 1 Product (not multiple products at once) into the user object on the button press.

    Future<void> addProduct(Product product) async {
        // Add the product to the user's product list
        products.add(product); 
    
        // toJson() is the function to convert `User` object to a `Json Map`
        await userCollection.doc(uid).update(toJson()); 
    }
    

    Then the complete User class,

    class UserData {
      UserData({
        required this.accommodations,
        required this.products,
      });
    
      final List<dynamic>
          accommodations; //successfully able to add single strings to list
    
      final List<dynamic>
          products; //unable to add multiple string objects to this list
    
      Map<String, dynamic> toJson() =>
          {"products": products.map((e) => e.toJson()).toList()};
    
      Future<void> addProduct(Product product) async {
        products.add(product);
    
        await userCollection.doc(uid).update(toJson());
      }
    }
    
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.