Reputation: 743
I am trying to understand the map()
operator of RxJS.
Below is one of the example with works as expected. In this example all names will be appended with text student one by one.
studentArray:string[]=['sam','robert','lisa'];
from(this.studentArray).pipe(map((s:string)=>s=s+' student')).subscribe(d=>console.log(d));
Now I have below sample code. With this code I am calling a service which returns array of ToDo objects. What I am trying to do is the iterate each ToDo object and return the updated object
But when I do so it gives an error and reason for the error is data
variable in the map
operator. With above example map operator is not getting single element of an array of ToDo but the entire array is being passed to the map.
Am I doing something wrong here?
Edit: Updated image.
Upvotes: 1
Views: 1908
Reputation: 5813
Follow @Vasileios Kagklis
's answer. He explains your issue. The rxjs map
pipe is completely different than the JavaScript higher order map
function. You shouldn't be assigning a value in the map
pipe with =
.
I'm not 100% sure what you're trying to accomplish with this but from what I can understand you might be looking for something like...
this.http.get<ToDo[]>(`....`)
.pipe(
map(data => data.map(todo => ({
...todo,
title: todo.title + 'append'
})
)
.susbscribe(todos => console.log(todos));
So the map
rxjs pipe, receives a ToDo[]
, so data
is a ToDo[]
not a single ToDo
. So once the data is emitted you have to iterate over that array and mutate each item in the array (JavaScript's higher order map
function) updating the title.
Upvotes: 0
Reputation: 826
You are using the map
operator incorrectly. The map
operator receives a value, transforms it, and returns the transformed value. You are doing an assignment instead. A valid example would be:
.pipe(
map((value: string) => value + 'append')
)
Also, your data
is not a single ToDo
but an array, i.e. ToDo[]
. So with data = data.title + 'append'
you are trying to assign a string
to a ToDo[]
.
If I understand correctly, you want to append something on each ToDo
's title
property. Then you would have to do something like this:
this.http.get<ToDo[]>('YOU-ENDPOINT-URL-HERE').pipe(
concatMap((dataArray: ToDo[]) => from(dataArray)), // from array to single objects
map((data: ToDo) => {
data.title += 'append'; // transform tittle
return data; // return transformed data
}),
toArray() // recreate array
).subscribe((d) => console.log(d));
EDIT:
Your first example is not equivalent to your use-case. The from
operator takes an array, in your example string[]
, and converts it into an Observable<string>
.
The http.get<Todo[]>
declares that the returned type from your backend is going to be an array. And this is the type of data that will be passed to your pipe, hence to your map
operator as well.
Upvotes: 0
Reputation: 849
It is not Angular-ish thing per say but it is more a Typescript compiler issue. It is doing its job correctly telling you that you are assigning something of type B
to something else of type C
. In our case here, it is the fact that you are assigning a string to an array of TODOs.
What @Jason White
mentioning in the comment is IMO the correct answer to solve your problem.
Upvotes: 1
Reputation: 5264
map()
function that you use is not JavaScript standard Array.map, it is the RxJs
map operator, it applies a project function to each value emitted (in your case, a single value is an array of ToDo
) by the source Observable, and emits the resulting values as an Observable.
Upvotes: 3