Dropdown select (Dart Angular Components) discards the second selection

Issue

I have the following example class:

import 'package:angular/angular.dart';
import 'package:angular_forms/angular_forms.dart';
import 'package:angular_components/angular_components.dart'
    show
        SelectionModel,
        HasUIDisplayName,
        Selectable,
        SelectableOption,
        StringSelectionOptions,
        MaterialDropdownSelectComponent,
        MaterialSelectSearchboxComponent,
        SelectionChangeRecord,
        ItemRenderer,
        CachingItemRenderer;

@Component(
    selector: 'example-select',
    templateUrl: 'example.html',
    styleUrls: const [
      'example.css'
    ],
    directives: const [
      CORE_DIRECTIVES,
      formDirectives,
      MaterialDropdownSelectComponent,
      MaterialSelectSearchboxComponent,
    ])
class ExampleSelect {
  int width = 0;
  List<SelectElement> valuesList;
  SelectionOptions<SelectElement> _elementListOptions;
  StringSelectionOptions<SelectElement> get elementOptions =>
      _elementListOptions;
  ItemRenderer<SelectElement> get itemRenderer => _itemRenderer;
  // Single Selection Model.
  final SelectionModel<SelectElement> singleSelectModel =
      new SelectionModel.withList(selectedValues: []);

// Label for the button for single selection.
  String get singleSelectLabel => singleSelectModel.selectedValues.isNotEmpty
      ? itemRenderer(singleSelectModel.selectedValues.first)
      : 'No Selection';

  dynamic get singleSelectedValue => singleSelectModel.selectedValues.isNotEmpty
      ? singleSelectModel.selectedValues.first.value
      : null;

  ExampleSelect() {
    singleSelectModel.selectionChanges.listen(updateModel);
    valuesList = <SelectElement>[
      new SelectElement(1, "First"),
      new SelectElement(2, "Second"),
      new SelectElement(3, 'Third')
    ];
    _elementListOptions = new SelectionOptions<SelectElement>(valuesList);
  }

  void updateModel(List<SelectionChangeRecord> record) {
    print(record);
  }

  static final ItemRenderer<SelectElement> _itemRenderer =
      new CachingItemRenderer<SelectElement>(
          (selectElement) => "$selectElement");
}

class SelectElement implements HasUIDisplayName {
  final value;
  final String label;

  const SelectElement(this.value, this.label);

  @override
  String get uiDisplayName => label;

  @override
  bool operator ==(Object other) => other is SelectElement && label == label;
  @override
  int get hashCode => label.hashCode;
  @override
  String toString() => uiDisplayName;
}

class SelectionOptions<T> extends StringSelectionOptions<T>
    implements Selectable {
  SelectionOptions(List<T> options)
      : super(options, toFilterableString: (T option) => option.toString());

  @override
  SelectableOption getSelectable(selectElement) =>
      selectElement is SelectElement
          ? SelectableOption.Selectable
          : SelectableOption.Disabled;
}

The html is as follows:

<material-dropdown-select
        [buttonText]="singleSelectLabel"
        [selection]="singleSelectModel"
        [options]="elementOptions"
        [width]="width"
        [itemRenderer]="itemRenderer">
</material-dropdown-select>

<br>

Selected: {{singleSelectLabel}}

Now, if I run this example, and I select the first element, everything works fine, but when I select the “Second” element, the dropdown return to not selected.

This is resumed by the print function that shows the following:

  1. [SelectionChangeRecord{added: [First], removed: []}]
  2. [SelectionChangeRecord{added: [], removed: [First]}]

What I’m doing wrong?

Solution

There is an error in your equals method:

@override
bool operator ==(Object other) => other is SelectElement && label == label;

Do you see it??

Should be

other.label == label

I’d probably suggest not overriding the equals method, but that is what is happening here. So when you select/unselect the widget is selecting/unselecting everything because you said they were equal.

Answered By – Ted Sander

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.