2

I have a output like below from an observable. I want to transform this output into a string format as for all true records "John~Ford,Fiat". I want to acheive this using RXJS operators. Can someone show me how can i get to this.

[{
  "name":"John",
  "age":30,
  "selected" : true,
  "cars": [
      { "selected":"true",  "name":"Ford", "models": "Mustang"},
      { "selected":"false", "name":"BMW", "models": "320" },
      { "selected":"true", "name":"Fiat", "models":"500" }
  ]
 },
 {
  "name":"alex",
  "age":40,
  "selected" : false
  "cars": [
      { "selected":"true",  "name":"tesla", "models": "x"},
      { "selected":"false", "name":"merc", "models": "300" },
      { "selected":"true", "name":"honda", "models":"accord" }
   ]
  }
]

I am able to filter the records but not sure how to format the to the string output("John~Ford,Fiat".)

myComp.myService.carOptions$.pipe(
      take(1),
      flatMap(carOptions => carOptions as options[]),
      filter(carOption => carOption.selected === true),
      flatMap(options => options.values as values[]),
      filter(optionValue => optionValue.isSelected === true),
      toArray()
);
4
  • Is the array at the top what comes out the the carOption$ obersvable? If so, this is just a normal array operation in a normal map. The filter operator you're using is for filtering out observable results, not for filtering within the results themselves. Commented Feb 25, 2020 at 18:11
  • @kurt Hamilton yes the array at the top is the output of the observable. Oh ok, so how can i use the filter operator in this case. Commented Feb 25, 2020 at 18:23
  • Is the "alex" in this example, a false record, due to its top-level "selected" : false ? Commented Feb 25, 2020 at 18:25
  • yes Alex is false record ... incase if Alex is true then output should be John~Ford,Fiat | Alex~tesla,Honda Commented Feb 25, 2020 at 18:27

2 Answers 2

3

This isn't an RxJS problem, it's a javascript array problem.

The filter RxJS operator guards the pipe and only lets values through that meet its criteria. It doesn't filter out items within the values that come through.

The take filter you have in there at the moment will only let the first value through and no more. You may not want to keep that in there, but that's not the primary issue here.

Instead, you want to take what's coming out of the observable, and transform it into a different value. This is done inside an RxJS map operator.

myComp.myService.carOptions$.pipe(
  map((result: any): string => {
    return result
      .filter(x => x.selected)
      .map(x => {
        const cars = x.cars
          .filter(x => x.selected)
          .map(x => x.name)
          .join(',');
        return `${x.name}~${cars}`;
      }).join('|');
  })
).subscribe(result => {      
  console.log(result);
});

That map inside the function is transforming the array in your question to an array of strings matching your criteria.

Firstly it only keeps the selected top-level objects. Then it maps each object to a string. That string is a concatenation of "name" "~" and a joined list of car names where selected is true.

I have assumed that car.selected should be a boolean type. You will need to amend the check if it is actually a string type.

DEMO: https://stackblitz.com/edit/angular-snatak

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

2 Comments

@kurl Hamilton thanks a lot. But when i use your code in my actual application, i get errors like "cannot find result" , string only refers to type but being used as value here , expected 1 2 arguments but got 3.
I accidentally removed some brackets. Try again
1

https://stackblitz.com/edit/angular-rxjs-filter-problem

  ngOnInit() {
    of(values)
      .pipe(
        map(items => items.filter(item => item.selected)),
        map(items =>
          items.map(item => {
            const cars = item.cars
              .filter(car => car.selected === "true")
              .map(car => car.name)
              .join(",");
            return item.name + "~" + cars;
          })
        )
      )
      .subscribe(val => {
        console.log(val);
        this.result = val;
        this.str = val.join(" | ");
      });
  }

John~Ford,Fiat | alex~tesla,honda

1 Comment

Thank you this was the complete answer for my case.

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.