Skip to content
This repository was archived by the owner on May 20, 2023. It is now read-only.

Commit db3b7c2

Browse files
cissyshinshahan
authored andcommitted
Improve the material auto suggest input api:
- Allow `selection` input to take selected value for single selection in addition to SelectionModel. - Expose `selection` output to emit selected value(s) on selection changes. - Add new example for the simplest case. PiperOrigin-RevId: 213941461
1 parent 8583594 commit db3b7c2

File tree

7 files changed

+157
-16
lines changed

7 files changed

+157
-16
lines changed

angular_components/lib/material_input/material_auto_suggest_input.dart

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ class MaterialAutoSuggestInputComponent extends MaterialSelectBase
220220
/// Listener for selection options changes.
221221
StreamSubscription _optionsListener;
222222

223+
StreamController _selectionChangeController;
224+
223225
/// Direction of popup scaling.
224226
///
225227
/// Valid values are `x`, `y`, or `null`.
@@ -347,12 +349,37 @@ class MaterialAutoSuggestInputComponent extends MaterialSelectBase
347349
}
348350
}
349351

350-
/// If set, auto suggest will use the supplied observable [SelectionModel]
351-
/// object.
352+
/// Emits the selected value(s) whenever selection changes.
352353
///
353-
/// Uses a single selection model by default.
354+
/// For single select, it will either be the selected value or null.
355+
/// For multi select, it will a list of selected values or an empty list.
356+
@Output()
357+
Stream get selectionChange {
358+
if (_selectionChangeController == null) {
359+
_selectionChangeController = new StreamController();
360+
}
361+
return _selectionChangeController.stream;
362+
}
363+
364+
/// Sets the selected value or selection model for the input.
365+
///
366+
/// Accepts either a [SelectionModel], a selected value or null.
367+
@Input('selection')
368+
set selectionInput(dynamic value) {
369+
if (value is SelectionModel) {
370+
selection = value;
371+
} else if (value == null) {
372+
selection.clear();
373+
} else {
374+
assert(
375+
isSingleSelect,
376+
'Passing selected value through `selection` input is only supported '
377+
'for single select.');
378+
selection.select(value);
379+
}
380+
}
381+
354382
@override
355-
@Input()
356383
set selection(SelectionModel selection) {
357384
super.selection = selection;
358385

@@ -379,6 +406,15 @@ class MaterialAutoSuggestInputComponent extends MaterialSelectBase
379406
_lastSelectedItem != null ? itemRenderer(_lastSelectedItem) : '';
380407
}
381408
}
409+
if (_selectionChangeController != null) {
410+
if (isSingleSelect) {
411+
_selectionChangeController.add(selection.selectedValues.isNotEmpty
412+
? selection.selectedValues.first
413+
: null);
414+
} else {
415+
_selectionChangeController.add(selection.selectedValues);
416+
}
417+
}
382418
});
383419
}
384420

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Overview
2+
3+
Most selection widgets care about two data points: what is selectable and what is selected.
4+
5+
In ACX selection widgets, what is selectable is represented by the [`SelectionOptions`](https://github.com/dart-lang/angular_components/blob/master/angular_components/lib/model/selection/selection_options.dart) interface, while what is selected is represented by the [`SelectionModel`](https://github.com/dart-lang/angular_components/blob/master/angular_components/lib/model/selection/selection_model.dart) interface. Material auto select input uses these two interfaces via the `selectionOptions` and `selection` inputs, but additionally it has `inputText` which presents the text the user has entered.
6+
7+
Which input combinations to use for Material Auto Suggest Input depends on your use case.
8+
9+
If you are using the component to accept user entered content, and the list of options is used to assist content entry, you want to use `selectionOptions` and `inputText`. Together with the `inputTextChange` output, you can setup two-way binding for the input text.
10+
11+
HTML:
12+
```
13+
<material-auto-suggest-input
14+
[selectionOptions]="myOptions"
15+
[(inputText)]="myInput"
16+
...>
17+
</material-auto-suggest-input>
18+
```
19+
20+
Dart:
21+
```
22+
class MyView {
23+
final myOptions = ['Foo', 'Bar', 'Baz'];
24+
String myInput = 'Bar';
25+
}
26+
```
27+
28+
If you are using the component to select one or more items from a list of options, and the input is used for filtering, you want to use `selectionOptions` and `selection`. Together with the `selectionChange` output, you can setup two-way binding for the selected value.
29+
30+
HTML:
31+
```
32+
<material-auto-suggest-input
33+
[selectionOptions]="myOptions"
34+
[(selection)]="mySelection"
35+
...>
36+
</material-auto-suggest-input>
37+
```
38+
39+
Dart:
40+
```
41+
class MyView {
42+
final myOptions = [1, 2, 3];
43+
int mySelection = 2;
44+
}
45+
```
46+
47+
# The selectionOptions input
48+
49+
The `selectionOptions` input accepts either a `SelectionOptions` class or a generic `List`.
50+
51+
If a `List` is passed, a [`StringSelectionOptions`](https://github.com/dart-lang/angular_components/blob/master/angular_components/lib/model/selection/string_selection_options.dart) will be created with the list and the `ItemRenderer` if specified to support basic filtering.
52+
53+
If you need more advanced features, like grouped options, custom filtering or async search, you could also pass an implementation of `SelectionOptions`.
54+
55+
# The selection input & output
56+
57+
The `selection` input accepts either a `SelectionModel`, a selected value or null.
58+
59+
By default Material Auto Suggest Input uses [`SingleSelectionModel`](https://github.com/dart-lang/angular_components/blob/master/angular_components/lib/src/model/selection/single_selection_model_impl.dart). If a selected value is passed to the `selection` input, this value will be selected by the default selection model. If a null value is passed to the input, the default selection model will clear the selection.
60+
61+
If you need to use a `MultiSelectionModel` or a custom implementation of `SelectionModel`, you could also use the same input.
62+
63+
The `selectionChange` output emits the selected value(s) whenever selection changes. For single select, it will either be the selected value or null. For multi select, it will a list of selected values or an empty list.
64+
65+
For simpler single select use cases, you can use the `[(selection)]` syntax to setup two-way binding for your selected value.

examples/material_input_example/lib/gallery_section_config.dart

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import 'package:angular_components/material_input/material_number_accessor.dart'
88
import 'package:angular_components/material_input/material_percent_directive.dart';
99
import 'package:angular_gallery_section/annotation/gallery_section_config.dart';
1010

11-
import 'material_auto_suggest_input_demo.dart';
11+
import 'material_auto_suggest_input_full_demo.dart';
12+
import 'material_auto_suggest_input_simple_demo.dart';
1213
import 'material_input_demo.dart';
1314
import 'material_input_mixins.dart';
1415
import 'material_input_number_value_accessor_demo.dart';
@@ -19,16 +20,31 @@ import 'material_percent_input_demo.dart';
1920
docs: [
2021
MaterialInputComponent,
2122
MaterialMultilineInputComponent,
23+
'package:angular_components/material_input/material_auto_suggest_input.md',
2224
MaterialAutoSuggestInputComponent,
2325
MaterialNumberValueAccessor,
2426
MaterialPercentInputDirective,
2527
],
2628
demos: [
2729
MaterialInputDemoComponent,
28-
MaterialAutoSuggestInputDemoComponent,
30+
MaterialAutoSuggestInputSimpleDemoComponent,
31+
MaterialAutoSuggestInputFullDemoComponent,
2932
MaterialPercentInputDemoComponent,
3033
MaterialInputMixinDemoComponent,
3134
MaterialInputNumberValueAccessorDemoComponent,
3235
],
3336
)
3437
class MaterialInputGallerySection {}
38+
39+
@GallerySectionConfig(
40+
displayName: 'Material Auto Suggest Input',
41+
docs: [
42+
'package:angular_components/material_input/material_auto_suggest_input.md',
43+
MaterialAutoSuggestInputComponent
44+
],
45+
demos: [
46+
MaterialAutoSuggestInputSimpleDemoComponent,
47+
MaterialAutoSuggestInputFullDemoComponent
48+
],
49+
)
50+
class MaterialAutoSuggestInputGallerySection {}

examples/material_input_example/lib/material_auto_suggest_input_demo.dart renamed to examples/material_input_example/lib/material_auto_suggest_input_full_demo.dart

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ import 'package:angular_components/model/selection/selection_model.dart';
1616
import 'package:angular_components/model/selection/selection_options.dart';
1717
import 'package:angular_components/model/selection/string_selection_options.dart';
1818
import 'package:angular_components/model/ui/has_factory.dart';
19-
import 'package:angular_gallery_section/annotation/gallery_section_config.dart';
2019

21-
import 'material_auto_suggest_input_demo.template.dart' as demo;
20+
import 'material_auto_suggest_input_full_demo.template.dart' as demo;
2221

2322
List<String> _numberNames = <String>[
2423
'one',
@@ -63,13 +62,8 @@ List<OptionGroup<List<int>>> _optionGroups = <OptionGroup<List<int>>>[
6362
], "Even less than 20")
6463
];
6564

66-
@GallerySectionConfig(
67-
displayName: 'Material Auto Suggest Input',
68-
docs: [MaterialAutoSuggestInputComponent],
69-
demos: [MaterialAutoSuggestInputDemoComponent],
70-
)
7165
@Component(
72-
selector: 'material-auto-suggest-input-demo',
66+
selector: 'material-auto-suggest-input-full-demo',
7367
directives: [
7468
formDirectives,
7569
MaterialAutoSuggestInputComponent,
@@ -80,11 +74,11 @@ List<OptionGroup<List<int>>> _optionGroups = <OptionGroup<List<int>>>[
8074
NgFor,
8175
NgIf,
8276
],
83-
templateUrl: 'material_auto_suggest_input_demo.html',
77+
templateUrl: 'material_auto_suggest_input_full_demo.html',
8478
styleUrls: ['material_auto_suggest_input_demo.scss.css'],
8579
preserveWhitespace: true,
8680
)
87-
class MaterialAutoSuggestInputDemoComponent {
81+
class MaterialAutoSuggestInputFullDemoComponent {
8882
static const _popupPositionsAboveInput = [
8983
RelativePosition.AdjacentTopLeft,
9084
RelativePosition.AdjacentTopRight,
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:angular/angular.dart';
6+
import 'package:angular_components/material_input/material_auto_suggest_input.dart';
7+
8+
@Component(
9+
selector: 'material-auto-suggest-input-simple-demo',
10+
directives: [MaterialAutoSuggestInputComponent],
11+
templateUrl: 'material_auto_suggest_input_simple_demo.html',
12+
styleUrls: ['material_auto_suggest_input_demo.scss.css'],
13+
)
14+
class MaterialAutoSuggestInputSimpleDemoComponent {
15+
final values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
16+
int selectedValue = 1;
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!--
2+
Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
3+
for details. All rights reserved. Use of this source code is governed by a
4+
BSD-style license that can be found in the LICENSE file.
5+
-->
6+
<div class="example">
7+
<h2>Simple single selection</h2>
8+
<material-auto-suggest-input
9+
[(selection)]="selectedValue"
10+
[selectionOptions]="values">
11+
</material-auto-suggest-input>
12+
<div>Selected value: {{selectedValue}}</div>
13+
</div>

0 commit comments

Comments
 (0)