Andrey Roklan
Andrey Roklan

Reputation: 11

Angular dart - custom input component with ngModel

I'm trying to create a custom input text component but I don't know how to make it work with the ngModel directive.

I've tried replicating the material angular_component input but can't understand how the inputText property is actually linked to the ngModel value and what is the purpose of DefaultValueAccessor directive.

This is how I expect to use my component:

<my-input-component [(ngModel)]="someProp"><my-input-component>

(where the content of my-input-component is just a plain <input type="text"> field with a label)

Any ideas or links to examples/docs will be greatly appreciated.

Upvotes: 0

Views: 398

Answers (1)

Andrey Roklan
Andrey Roklan

Reputation: 11

After debugging the angular_components code, I found the answer myself. You have to implement ControlValueAccessor and to register the ngValueAccessor provider (that actually was the missing part).

Here is my solution:

// my_custom_component.dart
@Component(
  selector: 'my-custom-component',
  templateUrl: '<div class="input-wrapper">{{value}}</div>',
  providers: [
    ExistingProvider.forToken(ngValueAccessor, MyCustomComponent),
  ],
)
class MyCustomComponent implements ControlValueAccessor<String> {
  String value;
  // ...could define a setter that call `_changeController.add(value)`

  final _changeController = StreamController<String>();

  @Output()
  Stream<String> get onChange => _changeController.stream;

  @override
  void writeValue(String newVal) {
    value = newVal ?? '';
  }

  @override
  void registerOnChange(callback) {
    onChange.listen((value) => callback(value));
  }

  // optionally you can implement the rest interface methods
  @override
  void registerOnTouched(TouchFunction callback) {}

  @override
  void onDisabledChanged(bool state) {}
}
// app_component.dart
@Component(
  selector: 'app-component',
  templateUrl: '''
    <my-custom-component [(ngModel)]="data"></my-custom-component>
  ''',
  directives: [
    NgModel,
    MyCustomComponent,
  ],
)
class AppComponent {
  String data;
}

Note: angular_component uses directives but the main idea is the same.

Upvotes: 1

Related Questions