#2: More interaction! Upload photos
Thatās nice to see some interaction in your application. You display a bunch of thumbnails, you can click on them to see whole photo, and click again to hide photo.
To do so, we created one BehaviorSubject and one Observable. Did you notice how we keep track of active photo? No need to remove old value, nor clean data. You just put next value on Subject and it becomes the current value. Data flows one way. Send some data to Subject ā react to it. Event happens, you send another piece data ā you react to it. Thatās RxJS bread and butter.
Next thing thatād be nice to have in photo gallery is photo upload. First thing: we create a new Component. Let your imagination run wild! If it uploads photos, letās call it: photo-upload
! This one is going to be fun! Here weāll use RxJS to process stream of incoming photos, pass it to photos service and display in our gallery.
Photo upload
We want to take some data from user. Soā¦ we should use HTML input! You probably used it for text input before, but it also has file version. How does it look? Roughly, like this:
Thatās a lot of attributes on the input
element! Letās walk through each attribute together.
Type file
indicates that our element will gather files. multiple="multiple"
means it accepts many files at once. [(ngModel)]="filesCollectionā
allows us to control value of input from Angular. accept="image/png, image/jpg, image/jpeg"
limits types of files we accept. (change)="handleFileInput($event.target.files)"
means, as youāve already may deduced, that every time new files come to your input, youāll handle them using handleFileInput
method.
The HTML is ready, letās proceed to our Component logic.
Handle new files
Do you think youāre ready to add new photos to your gallery? Because I think you are. Letās see how to implement handleFileInput
and break it down, piece by piece:
For starters we create constant imagesCollection
. File input returns value of type FileList
. FileList
doesnāt have familiar methods like map
or forEach
so it has to be transformed into Array. From now on we can use all Array methods on it.
The first thing weāre going to do with our images is take their contents out and save in browser-friendly format. Thatās what happens when we create constant imagesContent
. We take the array of images and map it to array of images content. Because reading file content may take long itās asynchronous. Therefore function readFileContent
returns Promise. It opens file, reads it into format browser understands and resolves Promise once the file is read.
Oh no! What now! So far, weāve been dealing with Observables and now we have Array of Promises! What do we do?!
Never fear! Iām gonna tell you a little secret. RxJS already has our backs. It is smart enough to recognize that in some situations thereās no visible difference between Observable and Promise. Both are objects that hold reference to value that will come sometime in future. Promise resolves only once, Observable can resolve many times, but sometimes itās not that much of a difference.
Now, weāre going to use RxJS function forkJoin
to create uploadedImages$
. Itāll take our Array of Promises, wait until they all resolve, then put all resolved values into one Array and pass it down to Observable. Itās so smart! Letās recap, once again, what it does for us. 1. We feed it with Array of Promises (objects that will have some value in future). 2. It waits for all Promises to resolve. 3. It collects data from all Promises, puts data in Array and returns Observable that holds this Array. Quite similar to JavaScript native Promise.all
, but returns Observable, so we can use all RxJS operators and functions on it!
And what should happen when we read all images? Take list of sources and merge it with list of images. When data is ready, send it to Photos service via newPhotos$
Subject.
Last updated
Was this helpful?