Andreas Hunter
Andreas Hunter

Reputation: 5024

Flutter: Can't add item to list with callback

In my this file I receive list of Properties from API and generate like this interface:

enter image description here

Problem: When I tried enter volume and check result then receive null and new property not added to list. I add new property using setProperty callback in my code. All enteren properties will be saved in List<PropertyData> selectedProperties; variable.

Code:

class FarmerPropertyScreen extends StatefulWidget {
  final bool isEdit;

  FarmerPropertyScreen({Key key, this.isEdit}) : super(key: key);

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

class _FarmerPropertyScreenState extends State<FarmerPropertyScreen> {
  List<PropertyModel> properties;
  ApiDataService apiDataService = getItInstance<ApiDataService>();
  List<PropertyData> selectedProperties;

  Future getProperties() async {
    if (properties == null) {
      var res = await apiDataService.getProperties();
      if (res != null) {
        print("Properties received from  API");
        setState(() {
          properties = res;
        });
      }
    }
  }

  @override
  void initState() {
    getProperties();
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  void setProperty(double volume, int id) {
    print("CALLBACK INFO");
    print("ID");
    print(id);
    print("VOLUME");
    print(volume);
    if (selectedProperties != null && selectedProperties.length > 0) {
      print("REMOVED TO UNIQUE LIST");
      selectedProperties.removeWhere((item) => item.id == id);
    }
    if (volume > 0) {
      print("ADDED NEW PROPERTY");
      setState(() {
        selectedProperties.add(PropertyData(id: id, volume: volume));
      });
    }
  }

  List<Widget> propertiesList() {
    List<Widget> children = [];
    if (properties != null && properties.length > 0) {
      for (int i = 0; i < properties.length; i++) {
        children.add(
          FarmerObject(
            id: properties[i].id,
            title: properties[i].title,
            volume: 0.0,
            enabled: i == 0 ? true : false,
            callback: setProperty,
          ),
        );

        if (i != properties.length - 1) {
          children.add(
            SizedBox(height: MediaQuery.of(context).size.height * 0.02),
          );
        }

        if (i == properties.length - 1) {
          children.add(SizedBox(height: 45.h));
          children.add(
            FlatButton(
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(5.0),
              ),
              minWidth: 206.w,
              padding: EdgeInsets.symmetric(vertical: 12.h),
              disabledColor: Colors.black12,
              disabledTextColor: Colors.blueGrey,
              onPressed: () {
                print("CHECK ADDED PROPERTIES");
                print(selectedProperties);
                return null;
              },
              color: primaryColor,
              child: Text(
                'Check',
                style: TextStyle(
                  color: Color(0xFF2B2B2B),
                  fontWeight: FontWeight.w500,
                  fontSize: 15.sp,
                ),
              ),
            ),
          );
          children.add(
            SizedBox(height: MediaQuery.of(context).size.height * 0.06),
          );
        }
      }
    }

    return children;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        centerTitle: true,
        title: Text(widget.isEdit == true ? 'Edit' : 'Continue'),
      ),
      body: Column(
        children: [
          widget.isEdit == true
              ? Container()
              : Container(
                  padding: EdgeInsets.only(
                    top: 30.h,
                    left: 25.w,
                    right: 25.w,
                  ),
                  child: Column(
                    children: [
                      Container(
                        alignment: Alignment.center,
                        child: Text(
                          'Step - 3',
                          style: TextStyle(
                            color: Color(0xFF2B2B2B),
                            fontSize: 14.sp,
                          ),
                        ),
                      ),
                      SizedBox(height: 35.h),
                      SignUpHeader('What do you have?', 'give'),
                      SizedBox(height: 15.h),
                    ],
                  ),
                ),
          Expanded(
            child: SingleChildScrollView(
              child: Container(
                padding: EdgeInsets.only(
                  top: 10.h,
                  left: 25.w,
                  right: 25.w,
                ),
                child: Column(
                  children: propertiesList(),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class FarmerObject extends StatefulWidget {
  final int id;
  final String title;
  final double volume;
  final bool enabled;
  final Function(double, int) callback;

  FarmerObject({
    this.id,
    this.volume,
    this.callback,
    this.title,
    this.enabled,
  });

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

class _FarmerObjectState extends State<FarmerObject> {
  bool status = false;
  int divisions;
  var priceController = new MoneyMaskedTextController(
      decimalSeparator: '.', thousandSeparator: ',');

  @override
  void initState() {
    setState(() {
      if (widget.volume != null) {
        priceController.updateValue(widget.volume);
      }

      status = widget.enabled;
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(left: 10, right: 4),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.only(
            topLeft: Radius.circular(5),
            topRight: Radius.circular(5),
            bottomLeft: Radius.circular(5),
            bottomRight: Radius.circular(5)),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withOpacity(0.25),
            spreadRadius: 0,
            blurRadius: 2,
            offset: Offset(0, 0),
          ),
        ],
      ),
      child: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(widget.title),
              Switch(
                  value: status,
                  activeColor: primaryColor,
                  inactiveThumbColor: Color(0xFFAFAFAF),
                  onChanged: (bool val) {
                    setState(() {
                      status = val;
                    });
                    if (val == false || priceController.numberValue == 0) {
                      widget.callback(0.0, widget.id);
                    } else {
                      print("Setted again");
                      print(priceController.numberValue);
                      widget.callback(priceController.numberValue, widget.id);
                    }
                  })
            ],
          ),
          status == true
              ? Column(
                  children: [
                    FadeInRight(
                      duration: Duration(milliseconds: 800),
                      child: Container(
                        // alignment: Alignment.centerRight,
                        decoration: BoxDecoration(
                          color: Colors.white,
                          borderRadius: new BorderRadius.circular(5.0),
                          boxShadow: [
                            BoxShadow(
                              color: Colors.white,
                              // spreadRadius: 1,
                              // blurRadius: 3,
                            ),
                          ],
                        ),
                        child: TextFormField(
                          validator: (value) {
                            return null;
                          },
                          controller: priceController,
                          onChanged: (val) {
                            print("VALUE CHANGED!");
                            double enteredPrice = priceController.numberValue;
                            widget.callback(enteredPrice, widget.id);
                          },
                          keyboardType: TextInputType.number,
                          textAlign: TextAlign.start,
                          maxLines: 1,
                          maxLength: 18,
                          maxLengthEnforced: true,
                          decoration: InputDecoration(
                            isDense: true,
                            hintText: 'Enter volume',
                            contentPadding: EdgeInsets.all(0),
                            counterText: '',
                            filled: true,
                            fillColor: Colors.white,
                            border: OutlineInputBorder(
                              borderRadius: new BorderRadius.circular(10.0),
                              borderSide: BorderSide.none,
                            ),
                            suffixIcon: Padding(
                              padding: EdgeInsets.all(15),
                              child: Text(
                                'volume',
                                textAlign: TextAlign.right,
                                style: TextStyle(
                                  color: Color(0xFFAFAFAF),
                                  fontSize: 14.sp,
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                )
              : SizedBox(height: 0),
        ],
      ),
    );
  }
}

class PropertyData {
  final int id;
  final double volume;

  PropertyData({this.id, this.volume});
}

Maybe my logic is wrong in this file to save new items in the list?

Upvotes: 1

Views: 567

Answers (1)

reverie_ss
reverie_ss

Reputation: 2694

The issue is in List<PropertyData> selectedProperties;

By default, the value in selectedProperties will be null. So, when you are trying to add, it basically fails.

Replace it with, List<PropertyData> selectedProperties = [];

Upvotes: 2

Related Questions