Явно укажите тип для выбора материала вместо динамического - PullRequest
0 голосов
/ 04 февраля 2020

Задача

В AngularDart я хочу выбрать несколько Foo объектов с помощью material-dropdown-select и сохранить выбранные значения в реактивной форме.

Мой подход

    import 'package:angular/angular.dart';
    import 'package:angular_components/angular_components.dart';
    import 'package:angular_forms/angular_forms.dart';

    @Component(
      selector: 'my-app',
      template: '''
        <form [ngFormModel]="form">
          <material-dropdown-select 
            multi 
            ngControl="control1"
            [options]="options"
            [itemRenderer]="renderer"
          >
          </material-dropdown-select>
        </form>
      ''',
      directives: [
        formDirectives,
        MaterialDropdownSelectComponent,
        MultiDropdownSelectValueAccessor,
      ],
      providers: [
        materialProviders,
      ],
    )
    class AppComponent {
      var options = SelectionOptions.fromList([Foo(50, 'op1'), Foo(51, 'op2'), Foo(52, 'op3')]);
      var form;

      AppComponent() {
        form = ControlGroup({
          'control1': Control<List<Foo>>(<Foo>[]),
        });
      }

      String renderer(Foo entry) => '${entry.id}: ${entry.title}';
    }

    class Foo {
      int id;
      String title;

      Foo(this.id, this.title);
    }

Проблема

Мой пользовательский рендер не может быть применен из-за исключения из кода шаблона:

EXCEPTION: Expected a value of type '(dynamic) => String', but got one of type '(Foo) => String'

Откуда появился dynamic? Я думал, что средство доступа к значению принимает тип Foo из options! Без этого средства рендеринга компонент появляется, но выбор любого элемента приводит к следующему:

Error: Type 'List<dynamic>' should be 'List<Foo>' to implement expected type 'List<Foo>'.

Он выбрасывает из файла material_dropdown_material_accessor.dart , MultiDropdownSelectValueAccessor class:

    @override
    void registerOnChange(callback) {
      selectionChangesSub = selectionModel.selectionChanges.listen((_) {
        callback(selectionModel.selectedValues?.toList());
      });
    }

И снова - откуда это dynamic появляется? Реально ли использовать раскрывающийся список материалов с пользовательскими типами?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2020

Root причина

Проблема заключалась в том, что MaterialDropdownSelectComponent<T> и MultiDropdownSelectValueAccessor<T> являются обобщенными c директивами . T по умолчанию dynamic.

Решение

Существует экспериментальная функция AngularDart - directiveTypes. Это позволяет указывать тип generi c для любой директивы в шаблоне компонента. В моем случае пропущены следующие строки:

    @Component(
        ...
        directiveTypes: [
            Typed<MaterialDropdownSelectComponent<Foo>>(),
            Typed<MultiDropdownSelectValueAccessor<Foo>>(),
        ],
    )
    class AppComponent {
        ...
    }

Я наткнулся на это при выпуске GitHub . Любопытно, что пользователи TypeScript делают для работы вокруг этого .

0 голосов
/ 05 февраля 2020

Полагаю, что MultiDropdownSelectValueAccessor реализует ControlValueAccessor<List<dynamic>>. Возможно, вам нужно реализовать собственный метод доступа к значениям, например:

@Directive(
  selector : 'you-must-set-correct-selector-here`
)
class FooMultiDropdownSelectValueAccessor implements ControlValueAccessor<List<Foo>> {
  ...
}

Селектор может вводить некоторый атрибут, например, [list-type=foo]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...