0

I have a list of all deals _deals and a list of selected deals _selectedDeals. Deals can be added to or removed from the list _selectedDeals from another class. So if a new deal is added/removed, I want to rebuild this DealsWidget so the newly added/removed deal is properly reflected in UI.

And I'm using BookButton stateful widget, to show if a deal is selected or not. When isBooked is true, it means that the deal is selected.

I planned to achieve this behavior by calling the refresh() function of DealsWidget after data is added/removed from that other class so it would rebuild everything and my UI is consistent with data, but nothing happened.

What I've found out is that rebuilding won't recreate BookButton widgets again. Their constructors are not called again. And that is why my updated value is not getting entertained, because I'm passing them in constructor of BookButton.

Can anyone explain why is this happening and how can I properly show which deals are selected and which are not?

DealsWidget

class DealsWidget extends StatefulWidget {

  final List<Deal> _deals;
  final List<Deal> _selectedDeals;

  final DealSelectionListener _dealSelectionListener;

  DealsWidget(
    Key dealsKey,
    this._deals,
    this._selectedDeals,
    this._dealSelectionListener,
  ) : super(key: dealsKey);

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

class DealsWidgetState extends State<DealsWidget> {

  @override
  Widget build(BuildContext context) {

    final totalDeals = widget._deals.length;

    return ListView.builder(
      physics: NeverScrollableScrollPhysics(),
      itemCount: totalDeals,
      shrinkWrap: true,
      itemBuilder: (context, index) {

        final deal = widget._deals[index];
        final isSelected = widget._selectedDeals.contains(deal);
        
        return Container(
          color: Colors.white,
          padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
          child: BookButton(
            isSelected,
            (isBooked) {
              if (isBooked) {
                widget._dealSelectionListener._onSelected(deal);
              } else {
                widget._dealSelectionListener._onDeselected(deal);
              }
            }
          ),
        );
      }
    );
  }

  void refresh() {

    print('Refreshing deals');

    setState(() {
      
    });
  }
}

BookButton

class BookButton extends StatefulWidget {

  final bool isBooked;
  final OnBookChangedListener listener;

  BookButton(this.isBooked, this.listener);

  @override
  BookButtonClass createState() => BookButtonClass(isBooked);
}
  
class BookButtonClass extends State<BookButton> {

  bool isBooked;

  BookButtonClass(this.isBooked);

  void check(bool check) {
    setState(() {
      isBooked = check;
      widget.listener.call(isBooked);
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return FlatButton(
      onPressed: (){
        setState(() {
          isBooked = !isBooked;
          widget.listener.call(isBooked);
        });
      },
      child: Text(
        isBooked ? AppStrings.unbook.toUpperCase() : AppStrings.book.toUpperCase(),
        style: TextStyle(
          color: isBooked ? AppColors.accentColor : Colors.white,
          fontSize: 12,
        ),
      ),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(5),
        side: BorderSide(
          color: AppColors.accentColor,
          width: isBooked ? 1 : 0,
        )
      ),
      color: isBooked ? Colors.transparent : AppColors.accentColor,
    );
  }
}
Bugs Happen
  • 2,169
  • 4
  • 33
  • 59
  • Try to look at this https://dartpad.dev/3d7ca93535204901fe67776d9678b0b7. I know this is far from your question but it might give you an idea on just using setstate().. this example, uses a static global class to hold, read, update data and with setstate it will notify some changes. – Raine Dale Holgado Sep 23 '20 at 02:08
  • @Reign I've check it, it is doing the same thing I'm doing. But it's not working at my end. Maybe because my widgets are in a `List`? – Bugs Happen Sep 23 '20 at 04:19

1 Answers1

0

in this case you should use a Provider, becouse the widget needs to known when to rebuild.

Or if you think that Provider its kind of hard to learn now, try using a SetState() on your event ClickButton, this shoud resolve

Look what i did in my Case

So in my class with the data i used a the change changeNotifier

class PartnerControler extends ChangeNotifier {
....
changeNotifiers()
}

in the display class i used this

ChangeNotifierProvider(
                  create: (context) => partnerControler,
                  child: buildPartnerList(context),
                ),

 Widget buildPartnerList(BuildContext context) {
return Column(
      children: <Widget>[
Consumer<PartnerControler>(
          builder: (context, partnercontroler, child) {
return (Expanded(
              child: ListView.builder(
itemCount: partnerControler.partnerListFiltered.length,
..
mcachopas
  • 21
  • 5
  • I don't know about `Provider`. But I _am_ calling `setState()` on my event. The event happens in another class. It adds/removes data and then I call `refresh()` function, which calls `setState()` – Bugs Happen Sep 22 '20 at 13:39
  • See if my example can help you – mcachopas Sep 23 '20 at 11:09