Search code examples
angularangular2-templatengfor

Split comma separated string to array


I have a string of comma separated values like

let options = '1, FIRST,2, SECOND,3, THIRD,4, FOURTH'

Requirement: There will be a space after first comma which is next to number. I need to split comma only after each word.

I need to convert this options to array in Angular html to show it in dropdown

<mat-select #  multiple>
  <mat-option *ngFor="let option of options.split(',')" [value]="option">{{option }}</mat-option>
</mat-select>

Expected result:

1, FIRST
2, SECOND
3, THIRD
4, FOURTH

What I got with split(,) is

1
FIRST
2
SECOND
3
THIRD
4
FOURTH

Updated Question: I tried the solution provided here,

let options = '1, FIRST,2, SECOND,3, THIRD,4, FOURTH';
let splitOptions = options.split(/,(?=\d)/);
let splitOptionsWithQuotes = options.split('/^,(?=\d)$/');

for (let options of splitOptions) {
console.log(options);
}

for (let options of splitOptionsWithQuotes) {
console.log(options);
}
options.split(/,(?=\d)/) is working in TypeScript compiler. 
Output:
[LOG]: "1, FIRST" 
[LOG]: "2, SECOND" 
[LOG]: "3, THIRD" 
[LOG]: "4, FOURTH" 
options.split('/,(?=\d)/') is not working in HTML or TypeScript compiler. This results in 
[LOG]: "1, FIRST,2, SECOND,3, THIRD,4, FOURTH" 

Putting regex in single quotes not working in html. I tried executing the same in typescriptlang-org online compiler


Solution

  • I imagine you want to have an array with properties "value" and "text"

      const options='1, FIRST,2, SECOND,3, THIRD,4, FOURTH'
      const optionsArray=options.split(',').reduce(
              (a:{value:number,text:string}[],
               b:string,
               i:number)=>{
                    if (i%2)
                       a[Math.floor(i/2)].text=b.trim();
                    else
                       a.push({value:+b,text:''})
               return a
              },[])
    

    then optionsArray becomes like

    [ { "value": 1, "text": "FIRST" }, { "value": 2, "text": "SECOND" }, 
      { "value": 3, "text": "THIRD" }, { "value": 4, "text": "FOURTH" } ] 
    

    Update If we want an array like

    [ "1, FIRST", "2, SECOND", "3, THIRD", "4, FOURTH" ] 
    

    We can use

    optionsArray=options.replace(/\,(\d)/g,"|$1").split('|')
    

    First repalce the ","+digit by "|"+digit and then split by "|"

    A stackblitz

    Update 2, when we have a select with options it's a good idea that the select was "feed" with an array of object with two properties: "value" and "text".

    So I suggest

      rankings: Array<ColumnType> = [
        {
          id: 'schoolRanking',
          options: this.schoolOptions.map((x) => {
            const pair = x.split(',');
            return { value: +pair[0], text: pair[1] };
          }),
        },
        {
          id: 'collegeUGRanking',
          options: this.collegeUGOptions.map((x) => {
            const pair = x.split(',');
            return { value: pair[0], text: pair[1] };
          }),
        },
        {
          id: 'levels',
          options: this.collegePGOptions.map((x) => ({ value: x, text: x })),
        },
      ];
      allRankingss = this.rankings.map((x) => x.id);
    

    We define a rakningForm like

      rankingForm: FormGroup = new FormGroup({
        schoolRanking: new FormControl(0),
        collegeUGRanking: new FormControl(''),
        levels: new FormControl(''),
      });
    

    And our .html becomes more easy

    <div [formGroup]="rankingForm">
      <table mat-table class="mat-elevation-z8">
        <ng-container
          [matColumnDef]="ranking"
          *ngFor="let ranking of allRankingss;let i=index"
        >
          <mat-header-cell *matHeaderCellDef [id]="ranking">
            <mat-form-field>
              <mat-select [formControlName]="ranking" placeholder="Dropdown">
                <mat-option
                  *ngFor="let rank of rankings[i].options"
                  [value]="rank.value"
                >
                  {{ rank.text }}
                </mat-option>
              </mat-select>
            </mat-form-field>
          </mat-header-cell>
        </ng-container>
    
        <mat-header-row
          *matHeaderRowDef="allRankingss; sticky: true"
        ></mat-header-row>
        <mat-row *matRowDef="let row; columns: allRankingss"></mat-row>
      </table>
    </div>
    

    see your forked stackblitz