Home > OS >  I want to add items inside an array
I want to add items inside an array

Time:11-12

I am trying to add items inside an empty array. I am using Dio package to send post request. All others codes are working fine. But Here I am stucj with this issue. I took an empty array. Then I tried setState function to add item to the empty list. I am printing the list every time it got pressed. But I am getting empty array.

Actually I am trying to add products into the empty array and send post request.

Here is my code:

Consumer<ProductController>(
                        builder: ((context, value, child) {
                          // log('${value.products[0].results?.length.toString()}');
                          if (value.products.isNotEmpty) {
                            return Container(
                                height: maxHeight * 0.3,
                                child: ListView.builder(
                                  itemCount: value.products[0].results!.length,
                                  itemBuilder: (context, index) {
                                    return Card(
                                      child: ListTile(
                                        title: Text(value
                                            .products[0].results![index].name!),
                                        leading: IconButton(
                                          icon: const Icon(Icons.add),
                                          onPressed: () {
                                            setState(() {
                                              _lists.add(value.products[0]
                                                  .results![index].id);
                                              _lists = productIds;
                                              print("LISTS  >>>> $_lists");
                                            });
                                          },
                                        ),
                                        trailing: const Icon(Icons.done),
                                      ),
                                    );
                                  },
                                ));
                          } else {
                            return const CircularProgressIndicator();
                          }
                        }),
                      ),

Here is my Model:

class DisplayModel {
  String? status;
  List<Results>? results;

  DisplayModel({this.status, this.results});

  DisplayModel.fromJson(Map<String, dynamic> json) {
    status = json['status'];
    if (json['results'] != null) {
      results = <Results>[];
      json['results'].forEach((v) {
        results!.add(new Results.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['status'] = this.status;
    if (this.results != null) {
      data['results'] = this.results!.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class Results {
  int? id;
  List<Products>? products;
  List<Catalogs>? catalogs;
  String? name;
  Null? description;
  String? category;
  String? templateName;
  Null? bannerText;

  Results(
      {this.id,
      this.products,
      this.catalogs,
      this.name,
      this.description,
      this.category,
      this.templateName,
      this.bannerText});

  Results.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    if (json['products'] != null) {
      products = <Products>[];
      json['products'].forEach((v) {
        products!.add(new Products.fromJson(v));
      });
    }
    if (json['catalogs'] != null) {
      catalogs = <Catalogs>[];
      json['catalogs'].forEach((v) {
        catalogs!.add(new Catalogs.fromJson(v));
      });
    }
    name = json['name'];
    description = json['description'];
    category = json['category'];
    templateName = json['template_name'];
    bannerText = json['banner_text'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    if (this.products != null) {
      data['products'] = this.products!.map((v) => v.toJson()).toList();
    }
    if (this.catalogs != null) {
      data['catalogs'] = this.catalogs!.map((v) => v.toJson()).toList();
    }
    data['name'] = this.name;
    data['description'] = this.description;
    data['category'] = this.category;
    data['template_name'] = this.templateName;
    data['banner_text'] = this.bannerText;
    return data;
  }
}

class Products {
  int? id;
  String? name;
  Null? unit;
  String? price;
  Null? salePrice;
  String? image;
  Null? category;
  Null? badge;

  Products(
      {this.id,
      this.name,
      this.unit,
      this.price,
      this.salePrice,
      this.image,
      this.category,
      this.badge});

  Products.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    unit = json['unit'];
    price = json['price'];
    salePrice = json['sale_price'];
    image = json['image'];
    category = json['category'];
    badge = json['badge'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['name'] = this.name;
    data['unit'] = this.unit;
    data['price'] = this.price;
    data['sale_price'] = this.salePrice;
    data['image'] = this.image;
    data['category'] = this.category;
    data['badge'] = this.badge;
    return data;
  }
}

class Catalogs {
  int? id;
  Null? name;
  Null? unit;
  Null? price;
  Null? salePrice;
  String? image;
  Null? video;
  Null? badge;

  Catalogs(
      {this.id,
      this.name,
      this.unit,
      this.price,
      this.salePrice,
      this.image,
      this.video,
      this.badge});

  Catalogs.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    unit = json['unit'];
    price = json['price'];
    salePrice = json['sale_price'];
    image = json['image'];
    video = json['video'];
    badge = json['badge'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['name'] = this.name;
    data['unit'] = this.unit;
    data['price'] = this.price;
    data['sale_price'] = this.salePrice;
    data['image'] = this.image;
    data['video'] = this.video;
    data['badge'] = this.badge;
    return data;
  }
}

Here is my Post controller:

Future<bool> addDisplay(String name, String category, String templateName,
      File catalogsImage, File catalogsVideo, List<Products> productIds) async {
    try {
      // String fileName = catalogsImage.path.split('/').last;
      var token = localStorage.getItem('access');
      Dio dio = Dio();
      FormData formData = FormData.fromMap({
        "name": name,
        "category": category,
        "template_name": templateName,
        "catalogs[0]image": await MultipartFile.fromFile(catalogsImage.path),
        "catalogs[0]video": await MultipartFile.fromFile(catalogsVideo.path),
        "products": productIds
      });

      var response = await dio.post(url,
          data: formData,
          options: Options(headers: {"Authorization": "Bearer $token"}));

      if (response.statusCode == 200) {
        notifyListeners();
        return true;
      } else {
        return false;
      }
    } on DioError catch (e) {
      print(e);
      return false;
    }
  }

here is the full code of front end:

// ignore_for_file: sized_box_for_whitespace
import 'dart:developer';

import 'package:digitaldisplay/controllers/DisplayController.dart';
import 'package:digitaldisplay/controllers/ProductController.dart';
import 'package:digitaldisplay/models/DisplayModel.dart';
import 'package:digitaldisplay/views/widgets/Display.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
import 'dart:io';

class CreateDisplayMobile extends StatefulWidget {
  const CreateDisplayMobile({super.key});

  @override
  State<CreateDisplayMobile> createState() => _CreateDisplayMobileState();
}

class _CreateDisplayMobileState extends State<CreateDisplayMobile> {
  final ImagePicker picker = ImagePicker();

  String _name = "";
  String _category = "";
  String _templateName = "";
  File? catalogImage;
  File? _catalogVideo;
  List<Products> productIds = [];

  final _form = GlobalKey<FormState>();
  void _addDisplay() async {
    var isValid = _form.currentState!.validate();
    if (!isValid) {
      return;
    }
    _form.currentState!.save();
    bool create = await Provider.of<DisplayController>(context, listen: false)
        .addDisplay(_name, _category, _templateName, catalogImage!,
            _catalogVideo!, productIds);
    if (create) {
      print(create);
      showDialog(
          context: context,
          builder: (context) {
            return AlertDialog(
              title: Text("Created"),
              actions: [
                ElevatedButton(
                  child: const Text("Return"),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          });
    } else {
      showDialog(
          context: context,
          builder: (context) {
            return AlertDialog(
              title: Text("Failed to create display!"),
              actions: [
                ElevatedButton(
                  child: const Text("Return"),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          });
    }
  }

  @override
  void initState() {
    Provider.of<DisplayController>(context, listen: false).getDisplays();
    Provider.of<ProductController>(context, listen: false).getProducts();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    List _lists = [];
    final ButtonStyle buttonStyle1 = ElevatedButton.styleFrom(
      backgroundColor: const Color(0xFFc3232a),
      shape: const StadiumBorder(),
      minimumSize: const Size(100, 50),
    );
    final ButtonStyle buttonStyle2 = ElevatedButton.styleFrom(
      backgroundColor: const Color(0xFFc3232a),
      shape: const StadiumBorder(),
      minimumSize: const Size(100, 50),
    );
    final ButtonStyle buttonStyle3 = ElevatedButton.styleFrom(
      backgroundColor: const Color(0xFF111111),
      shape: const StadiumBorder(),
      minimumSize: const Size(100, 50),
    );

    double maxHeight = MediaQuery.of(context).size.height;
    double maxWidth = MediaQuery.of(context).size.width;

    return Scaffold(
        // backgroundColor: Colors.deepPurple[200],
        appBar: AppBar(
          elevation: 0,
          backgroundColor: const Color(0xFF111111),
          title: const Text(
            "Digital Display Generator",
            textAlign: TextAlign.end,
          ),
        ),
        body: SingleChildScrollView(
          child: Column(children: [
            const SizedBox(
              height: 10,
            ),
            Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Consumer<DisplayController>(
                  builder: (context, value, child) {
                    log('${value.displays[0].results?.length.toString()}');
                    return Container(
                      height: maxHeight * 0.6,
                      width: maxWidth * 0.9,
                      child: GridView.count(
                        crossAxisSpacing: 5,
                        crossAxisCount: 1,
                        scrollDirection: Axis.horizontal,
                        children: List.generate(
                            value.displays.isNotEmpty
                                ? value.displays[0].results!.length
                                : 0, (i) {
                          return Padding(
                            padding: const EdgeInsets.all(8.0),
                            child: DisplayCard(
                                displayName:
                                    value.displays[0].results![i].name!,
                                displayImage: value.displays[0].results![i]
                                    .catalogs![0].image!,
                                id: value.displays[0].results![i].id!),
                          );
                        }),
                      ),
                    );
                  },
                ),
              ],
            ),
            Form(
              key: _form,
              child: Center(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Padding(
                        padding: EdgeInsets.all(10.0),
                        child: Text(
                          "Enter Name",
                        )),
                    Padding(
                      padding: EdgeInsets.all(10),
                      child: TextFormField(
                        validator: (v) {
                          if (v!.isEmpty) {
                            return "Please Enter a valid name";
                          } else {
                            return null;
                          }
                        },
                        onSaved: (value) {
                          _name = value as String;
                        },
                        autofocus: false,
                        style: const TextStyle(
                            fontSize: 15.0, color: Colors.black),
                        decoration: InputDecoration(
                          hintText: 'Name',
                          filled: true,
                          fillColor: Colors.white,
                          contentPadding: const EdgeInsets.only(
                              left: 14.0, bottom: 6.0, top: 8.0),
                          focusedBorder: OutlineInputBorder(
                            borderSide: const BorderSide(
                                color: Color.fromARGB(255, 73, 57, 55)),
                            borderRadius: BorderRadius.circular(0.0),
                          ),
                          enabledBorder: UnderlineInputBorder(
                            borderSide: const BorderSide(color: Colors.grey),
                            borderRadius: BorderRadius.circular(0.0),
                          ),
                        ),
                      ),
                    ),
                    const Padding(
                        padding: EdgeInsets.all(10.0),
                        child: Text(
                          "Enter Template Name",
                        )),
                    Padding(
                      padding: EdgeInsets.all(10),
                      child: TextFormField(
                        validator: (v) {
                          if (v!.isEmpty) {
                            return "Please Enter a valid name";
                          } else {
                            return null;
                          }
                        },
                        onSaved: (value) {
                          _templateName = value as String;
                        },
                        autofocus: false,
                        style: const TextStyle(
                            fontSize: 15.0, color: Colors.black),
                        decoration: InputDecoration(
                          hintText: 'Template Name',
                          filled: true,
                          fillColor: Colors.white,
                          contentPadding: const EdgeInsets.only(
                              left: 14.0, bottom: 6.0, top: 8.0),
                          focusedBorder: OutlineInputBorder(
                            borderSide: const BorderSide(
                                color: Color.fromARGB(255, 73, 57, 55)),
                            borderRadius: BorderRadius.circular(0.0),
                          ),
                          enabledBorder: UnderlineInputBorder(
                            borderSide: const BorderSide(color: Colors.grey),
                            borderRadius: BorderRadius.circular(0.0),
                          ),
                        ),
                      ),
                    ),
                    const Padding(
                        padding: EdgeInsets.all(10.0),
                        child: Text(
                          "Enter Category Name",
                        )),
                    Padding(
                      padding: EdgeInsets.all(10),
                      child: TextFormField(
                        validator: (v) {
                          if (v!.isEmpty) {
                            return "Please Enter a valid name";
                          } else {
                            return null;
                          }
                        },
                        onSaved: (value) {
                          _category = value as String;
                        },
                        autofocus: false,
                        style: const TextStyle(
                            fontSize: 15.0, color: Colors.black),
                        decoration: InputDecoration(
                          hintText: 'Category Name',
                          filled: true,
                          fillColor: Colors.white,
                          contentPadding: const EdgeInsets.only(
                              left: 14.0, bottom: 6.0, top: 8.0),
                          focusedBorder: OutlineInputBorder(
                            borderSide: const BorderSide(
                                color: Color.fromARGB(255, 73, 57, 55)),
                            borderRadius: BorderRadius.circular(0.0),
                          ),
                          enabledBorder: UnderlineInputBorder(
                            borderSide: const BorderSide(color: Colors.grey),
                            borderRadius: BorderRadius.circular(0.0),
                          ),
                        ),
                      ),
                    ),
                    const Padding(
                        padding: EdgeInsets.all(10.0),
                        child: Text(
                          "Select Product",
                        )),
                    Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Consumer<ProductController>(
                        builder: ((context, value, child) {
                          // log('${value.products[0].results?.length.toString()}');
                          if (value.products.isNotEmpty) {
                            return Container(
                                height: maxHeight * 0.3,
                                child: ListView.builder(
                                  itemCount: value.products[0].results!.length,
                                  itemBuilder: (context, index) {
                                    return Card(
                                      child: ListTile(
                                        title: Text(value
                                            .products[0].results![index].name!),
                                        leading: IconButton(
                                          icon: const Icon(Icons.add),
                                          onPressed: () {
                                            setState(() {
                                              _lists.add(value.products[0]
                                                  .results![index].id);
                                              // _lists = productIds;
                                              print("LISTS  >>>> $productIds");
                                            });
                                          },
                                        ),
                                        trailing: const Icon(Icons.done),
                                      ),
                                    );
                                  },
                                ));
                          } else {
                            return const CircularProgressIndicator();
                          }
                        }),
                      ),
                    ),
                    Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: ElevatedButton(
                            onPressed: () {
                              _getImageFromGallery();
                              // displayController.createDisplay(
                              //     "name", "category", "templateName", "1");
                            },
                            child: Text("Add Image"),
                            style: buttonStyle1,
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: ElevatedButton(
                            onPressed: () {
                              _getVideoFromGallery();
                              // displayController.createDisplay(
                              //     "name", "category", "templateName", "1");
                            },
                            child: Text("Add Video"),
                            style: buttonStyle1,
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: ElevatedButton(
                            onPressed: () {
                              _addDisplay();
                            },
                            child: Text("Add Display"),
                            style: buttonStyle2,
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
          ]),
        ));
  }

  void _getImageFromGallery() async {
    XFile? pickedFile = await picker.pickImage(source: ImageSource.gallery);
    if (pickedFile != null) {
      setState(() {
        catalogImage = File(pickedFile.path);
      });
    }
  }

  void _getVideoFromGallery() async {
    XFile? filepick = await picker.pickImage(source: ImageSource.gallery);
    if (filepick != null) {
      setState(() {
        _catalogVideo = File(filepick.path);
      });
    }
  }
}

So after adding to the empty list I want to save it. How can I acquire that? Is there any solution for me?

CodePudding user response:

The first issue, your main question's problem of list _lists being empty despite of adding values to the list.

You're declaring the _lists variable in the build method:

@override
Widget build(BuildContext context) {
  List _lists = []; // <---- this line

  ...
}

...which will redeclare the _lists variable every time there's a change in the state, which is as you're calling setState on adding value to the _lists:

setState(() {
  _lists.add(value.products[0].results![index].id);
  _lists = productIds;

  print("LISTS  >>>> $_lists");
});

So, the solution is to declare List _lists = []; from the build method to the _CreateDisplayMobileState class making it a top-level class variable.

class _CreateDisplayMobileState extends State<CreateDisplayMobile> {
  List _lists = [];

  ...
}

But then _lists = productIds; caught me thinking that you're trying to assign the _lists variable with the value of productIds variable which is empty and isn't updated anywhere by looking at your complete code. So, it makes no sense. You have to remove it.

Updated:

setState(() {
  _lists.add(value.products[0].results![index].id);
  
  // removed: _lists = productIds;

  print("LISTS  >>>> $_lists");
});

MAIN:

Also, then since you want to post the products id added to the _lists variable, it makes no sense to have both the variables _lists and productIds. Simply remove the _lists variable, change the type of the productsIds variable from List<Product> productIds to List<int> productIds and the addDisplay method productIdsparameter and then directly add product ids to the productIds.

setState(() {
  productIds.add(value.products[0].results![index].id);

  print("LISTS  >>>> $productIds");
});

Cheers

  • Related