0

I have an array of keywords as a property of my model. Now I want to show that one as a comma separated string in an input and transform it back to an array when user types.

I have created a join pipe to modify the output, but I don't know how to achieve a similar result with the (ngModelChange), but the opposite direction (transform to a string array from comma separated string).

<input type="text" [ngModel]="model.keywords | join:', '," (ngModelChange)="model.keywords=$event">

I know I can just add a method on a component and do it there, but what if I need to do this operation on many different components. I would like to register some function in angular so that it's available in html like a pipe.

Maybe this is not the best way to achieve what I need at all and I need to think in some other direction?

I can see 2 other alternatives:

  1. Create a component for the input like that will do the trick, but then it might happen I would need in some other (non-input) component e.g.

  2. Add an additional property on the model and make the model itself responsible for transformation (or use a class for keywords instead of just a string array that will have a separate constructor or something, not sure how to connect that to angular model).

Ilya Chernomordik
  • 27,817
  • 27
  • 121
  • 207
  • I would suggest [`ControlValueAccessor`](https://angular.io/docs/ts/latest/api/forms/index/ControlValueAccessor-interface.html). Here are few articles about it: http://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html, http://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel – Sasxa Oct 25 '16 at 07:09

1 Answers1

1

I ended up with a simple solution of adding additional get/set property to the model:

get keywordsString(): string {
    if (this.keywords) {
        return this.keywords.join(", ");
    }
    else {
        return "";
    }
}

set keywordsString(input: string) {

    if (input !== null) {
        this.keywords = input.split(",")
                             .map(t => t.trim())
                             .filter(t => t !== "");
    }
    else {
        this.keywords = [];
    }
}

This is much easier for the simple case than ControlValueAccessor suggested in comments (which is perfectly valid, just a bit too heavy weight for this simple case). Then I can just use [(ngModel)]="model.keywordsString" and it works very well it seems.

Ilya Chernomordik
  • 27,817
  • 27
  • 121
  • 207