0

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

2
  • doesn't seem like you can do it easily. You may have to make a method in the TypeScript part. Easiest way being a regex... Commented Jul 9, 2023 at 21:39
  • I tried regex. Mostly it works in Typescript, but same code not works in Angular html. Commented Jul 10, 2023 at 10:13

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

10 Comments

I need 1, FIRST as a separate word to show as a single text in dropdown. Thank you.
You can use <option [value]="option.value">{{option.value+' '+option.text}}</option>. But this "split" in value and text it's only if you want store "the value" (1,2,3,...). If you want to store "1, FIRST" (or "2, SECOND"), you can use some like optionsArray=options.replace(/\,(\d)/g,"|$1").split('|') -first replace the ,digit by |digit and after you use split (I update the answer)
options.replace(/\,(\d)/g,"|$1").split('|') has to be escaped with quotes in html like options.replace('/\,(\d)/g', '|$1').split('|'), but in html it is not working. may be I need to add some pipe.
I added stackblitz angular-ivy-dctyfk.stackblitz.io here. stackblitz.com/edit/… the options: [...this.schoolOptions] is returning as a comma separated string instead of array, as I returned ${col.options}-filter. If it returns as an array there is no need to split by comma to convert it as array.
Error: NG02200: Cannot find a differ supporting object 'LEVELA,LEVELB,LEVELC,LEVELD' of type 'string'. NgFor only supports binding to Iterables, such as Arrays. options: [] returns as this string instead of array. so I have added .split(',') to convert it as array. It beats me with the special case '1, FIRST, 2, SECOND'
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.