In AngularDart I want to choosing multiple Foo
objects via material-dropdown-select
and store selected values in the reactive form.
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);
}
My custom renderer can't be applied because of exception from template code:
EXCEPTION: Expected a value of type '(dynamic) => String', but got one of type '(Foo) => String'
Where from dynamic
has appeared? I thought the value accessor will takes the Foo
type from options
! Without that renderer the component appears, but choosing any item throws next:
Error: Type 'List<dynamic>' should be 'List<Foo>' to implement expected type 'List<Foo>'.
It throws from the material_dropdown_material_accessor.dart file, MultiDropdownSelectValueAccessor
class:
@override
void registerOnChange(callback) {
selectionChangesSub = selectionModel.selectionChanges.listen((_) {
callback(selectionModel.selectedValues?.toList());
});
}
And again — where that dynamic
appears from? Is it real to using material dropdown with custom types?
The problem was in the fact that MaterialDropdownSelectComponent<T>
and MultiDropdownSelectValueAccessor<T>
are generic directives. T
is dynamic
by default.
There is an experimental AngularDart feature — directiveTypes
. It allows to specify generic type for any directive in the component's template. In my case missing lines are the following:
@Component(
...
directiveTypes: [
Typed<MaterialDropdownSelectComponent<Foo>>(),
Typed<MultiDropdownSelectValueAccessor<Foo>>(),
],
)
class AppComponent {
...
}
I've stumbled on it at the GitHub issue. It's curious what TypeScript users do for working around that.