google / built_collection.dart

Immutable Dart collections via the builder pattern.
https://pub.dev/packages/built_collection
BSD 3-Clause "New" or "Revised" License
275 stars 52 forks source link

Unable to update nested BuiltList inside ListBuilder #259

Closed komritza closed 2 years ago

komritza commented 2 years ago

State is looking like this:

abstract class TravelDeductionsState
    implements Built<TravelDeductionsState, TravelDeductionsStateBuilder> {
  factory TravelDeductionsState(
          [void Function(TravelDeductionsStateBuilder) updates]) =
      _$TravelDeductionsState;

  TravelDeductionsState._();

  static Serializer<TravelDeductionsState> get serializer =>
      _$travelDeductionsStateSerializer;

  static TravelDeductionsStateBuilder initial() =>
      TravelDeductionsStateBuilder()
        ..loadedStatus = ApiRequestStatus.none
        ..days = ListBuilder<TravelDeduction>();

  BuiltList<TravelDeduction> get days;

  ApiRequestStatus get loadedStatus;
}

Trying to update the days and to add/remove entry like this:

TravelDeductionsStateBuilder _travelDeductionBreakfastToggled(
        TravelDeductionsStateBuilder state,
        TravelDeductionBreakfastToggledAction action) =>
    state
      ..days = state.days.build().rebuild((d) {
        if (d[action.index]
            .deductions
            .contains(TravelDeductionType.BREAKFAST)) {
          d[action.index]
              .deductions
              .rebuild((p0) => p0.remove(TravelDeductionType.BREAKFAST));
        } else {
          d[action.index]
              .deductions
              .rebuild((p0) => p0.add(TravelDeductionType.BREAKFAST));
        }
      }).toBuilder();

days looks like this:

TravelDeduction {
  date=2022-05-01,
  deductions=[],
}, TravelDeduction {
  date=2022-05-02,
  deductions=[],
}]

No matter what I do, deductions are always empty even though condition is met. Does someone know what am I missing here? Should I provide additional info so that someone can help out?

davidmorgan commented 2 years ago

Doing rebuild by itself doesn't modify anything; it returns a new instance. So you need to assign it to something. This snippet:

d[action.index]
              .deductions
              .rebuild((p0) => p0.remove(TravelDeductionType.BREAKFAST));

is throwing away the result; it needs to be something like

_d[action.index].deductions = d[action.index]
              .deductions
              .rebuild((p0) => p0.remove(TravelDeductionType.BREAKFAST));

there may be others, I didn't check the whole thing carefully, but that should be a start :)

komritza commented 2 years ago

Thanks for fast reply! I still have an issue where d[action.index].deductions = .... deductions is red underlined with the message

There isn’t a setter named 'deductions' in class 'TravelDeduction'.
Try correcting the name to reference an existing setter, or declare the setter.

So I definitely did something wrong.

davidmorgan commented 2 years ago

Then something like

d[action.index] = d[action.index].rebuild((b) => b.deductions = ...)
komritza commented 2 years ago

IT WORKED! This was such a painful thing for me, but I learned a lot on the way! I really appreciate your work!

davidmorgan commented 2 years ago

Great, happy to help :)