andrasferenczi / dart-data-plugin

IDEA plugin for generating utility methods for Dart data classes
148 stars 31 forks source link

CopyWith doesn't change value if null is passed #23

Open radoslawsobies opened 3 years ago

radoslawsobies commented 3 years ago

example MyObject.copyWith(field1: null) this will not set field1 to null value, old value remains

andrasferenczi commented 2 years ago

The original idea was to have non-null values in the field. Do you have a suggestion for what the generated code might look like?

dalewking commented 2 years ago

There are a number of solutions discussed here.

The basic idea is provide some optional-like wrapper class that must be used for nullable properties. Alternatively, you could provide additional methods for each nullable field to set it to null.

So perhaps in the example in addition to the regular copy constructor you would have another method name copyWithField1Null().

dalewking commented 2 years ago

Or perhaps there are additional boolean parameters to the copyWith like field1Null for each nullable field that says to interpret null as truly null.

So for example:

class Foo {
  final String? name;
}

Would generate a copy constructor like this:

  Foo copyWith({
    String? name,
    bool nameNull = false,
  }) {
    return Foo(
      name: name ?? (nameNull ? null : this.name),
    );
  }
ricardoemerson commented 7 months ago

A good solution for this is use ValueGetter like the sample bellow:


class ScheduleState {
  final ScheduleStatus status;
  final int? scheduleHour;
  final DateTime? scheduleDate;

  ScheduleState({required this.status, this.scheduleHour, this.scheduleDate});

  ScheduleState copyWith({
    ScheduleStatus? status,
    ValueGetter<int?>? scheduleHour,
    ValueGetter<DateTime?>? scheduleDate,
  }) {
    return ScheduleState(
      status: status ?? this.status,
      scheduleHour: scheduleHour != null ? scheduleHour() : this.scheduleHour,
      scheduleDate: scheduleDate != null ? scheduleDate() : this.scheduleDate,
    );
  }

And in controller to set values to nullable properties you must made a function call.

void selectHour(int hour) {
    if (hour == state.scheduleHour) {
      state = state.copyWith(scheduleHour: () => null);
    } else {
      state = state.copyWith(scheduleHour: () => hour);
    }
  }