Ionic 5 Angular Image Upload - File-Type Filtering and Verification - RXJS - 1 | LinkedIn Clone [14]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome back to the linkedin clone in this video we'll be working on image upload on our front end angular ionic application so let's give a demonstration of what we'll achieve today so as you can see here if we click on this profile image and we choose an image and i click open it updates and updates everywhere throughout the application and if i was just to make another cool post and we make that we can see that the image is preserved for that new post and also if we edit it it's also preserved and we can go ahead and we can delete that now it uses rxjs observables throughout the entire application for this to emit to all across our application however if we are to enter a document this is a valid mime type so it does not make it through the upload and we also use file type to check for the type so in the previous video we've checked it on the back end but i have made this text file and i've just renamed it to a dot png and if i upload that we won't get that uploaded because the actual typos was checked with file type and we'll be using this file type library for that so let's go ahead and get started so in the folder structure in the back end and the api i've just added this blank profile images in the images folder and this is going to be our default so if the user doesn't have an image you'll get this photo i will just need to make some quick tweaks so we can access our photos on the front end so just on the back end here in the feed controller i'm going to add the ability to get the images so i'm just going to add a get request here and we'll route it to the end point slash feed slash image and then whatever the file name is and recall that the file name is being converted into with our uuid into a unique id so it's not the same file name as on the um as you upload it so let's just go ahead and call this find image by name and we'll chuck in as a parameter here the file name so this is our file name it's a string and we'll also use this res decorator to be able to send our file so let's get that and we'll just check that if the file name actually exists so if the file name exists or it doesn't exist and if we take a look at the back end here we can see that if a user doesn't have an image the image path is just going to be null now it's got this null in brackets here so i'm just going to go ahead and check if the string null or the string in brackets null if either of those two are included in the passed in file name then there's no image to return we'll just say return otherwise we can return our image so we can say return res dot send file file name and where it is in location in relation to the root directory it's just in the images folder so that's that one we'll also want to add some in the user control because we're going to have the user which has its image and also the feed which are all of the users images so in the previous video we've set up this guard here so if you go to the image such user slash image you'll go ahead and you'll get back the file of the image but we could want the file name because if we get the file name back for the user then we're able to use this to be able to get it the file itself from an open uh non-guarded directory so we're going to go ahead and just copy this down and we're going to call this get image name so if we find the user image name and what would expect back here is an image name which is a string so we have our json coming back so we will need to get the id of the user from the request that's associated with the json web token so what we'll do here is we'll open up the user service and we can see that we've got update user image by id and find image name by user id and this goes into the user repo and just finds it finds the user by its id and we give back the image path so if we go into our user controller we can see that we return that method we pass in the user id that we found from the request we use a switch map because we're going to take the image name we're expecting back and rather than return the sending of the files what we'll do here is we'll just return the image name so that's all we really need to do on the back end side of things so what i'll do now since we're in our api folder is i'll just run a npm run start div and i'll go ahead and close these so we can concentrate on the front end for the rest of the project so in our front end before we start things off what we'll do is we'll go ahead and we'll just download file type so do an npm install file type in the linkedin folder here and they'll add it to our node modules and reference it in our package.json file so now we have that we can just run an ionic serve which opens our application and if we log in and we press f12 we're now back to our application now our images here these are just hard coded and what we want to do is have the ability so we can click on this image and this will spread throughout our entire application including these posts so in the profile summary component this dot post component the model associated with that the header and the pop-over component these are all posts relating to the user however these posts here these could be by anyone now it just so happens that all these posts are by this user but these images will need to be taken from the server separately depending on the author that created them so the two main parts we're breaking this up to is the authenticated user and then also the image of the author that posted their post so let's start off in the auth service so if we open up source we go into our app and we go into our auth service here we've already set a few things up so we have access to the user and we also can get if they're logged in get the user role get the user id so i'm going to add the ability to get a user stream so i'm going to create a getter get user stream and what this returns it returns the observable of the user type because we want to be able to get our user all throughout our application and in particular the image of the user but we also want to update the where we have this hard-coded name here in various spots in the application so we want a one uh main point where we can tap into that user stream and then we want to subscribe to it in all of the places so when it updates we'll propagate throughout our and all we need to do for this is just return the already existing user subject and because it's a behavior subject we'll need to convert it into an observable so people can subscribe to it and we the reason it isn't a subject in the first place is because we want to actively change it when we do things like if we change the image we want to actively change the user object in memory and the associated image file and then that will propagate throughout our application so this user as observable nice and simple got our user logged in user role user id now i'm going to make another getter to get the full name so i can get user full name and of course we could just subscribe to the user stream and do this work elsewhere in application but since i've already set up you know these other three methods here and i have that throughout our application i'm going to go ahead and just continue this sort of way and plus you only get back what you need as well so that's also a benefit so what i'll expect back for the full name is just a string so wait for that to occur so that's going to be an observable because we're going to return the current user subject as observable and of course this could be refactored so you could be subscribing to this user stream directly i'm just going to go ahead and keep doing this approach here so we know that this is going to return an observer of the user type so what we want to do is we want to return a different type of observable i.e a string so what we'll do is we'll use the switch map operator so for the user that we get back of the type user we'll go ahead and we'll just say the full name that's going to be equal to the user's first name plus a space plus the users dot last name and then of course we just want to convert that to an observable so we can wrap it in of and put in the full name here and what we want to do is we want to have another get method to get the full path of the image so i might break this down into two different parts so we'll have the regular getter to get the full or get the default image get the default full image path so this is going to return a string and it's just going to go and return our blank profile picture on our server so we can just go ahead and return that and the reason i'm doing it here is because we're going to use this throughout the application and if you do need to make a change you can just make it into one spot rather than everywhere so i'm just going to go ahead and this is on localhost 3000 so i'm just going to go ahead and copy this from postman and it's in our feed controller when we try and access an image and we can access it by the name blank profile picture because that's what i saved it as and i've already put it into the folder as you've seen earlier so that's the first route now i'm going to copy this down so i can have a get full image path and this will take in a image path or the slug of an image path [Music] i might just say image path or image name i'll call it image name image name because the name and the path of the slug is going to be the same and this is going to be a string so this is sort of like saying have this part here but this part here is going to be the dynamic part which is going to be the image name so we have the ability to get the default image full path if there's no image and we've got the ability to get the full image path if there is an image and an image name passed into that so that means we can create a get method for our user observable and we'll call this get user full image path because we're getting it for the user not for every uh post so this is just going to be a function and it's going to return a string [Music] and it's either going to return this or this depending on whether or not there are some if the user has an image so basically what we can do here is we can return this the user observable pipe into that we know it's returning a user now we want to return the image path which is a string so we use the switch map operator and that takes a user of the type user now we want to see if the author has an image so we'll make a constant variable called const auth has image and this is going to depend on if the user has an image path or not i'm just going to go to my user object and it appears that we do not have the image path added just yet and that's okay because we can just add it and we'll just add it below roll here i say optional parameter and i suppose post could be optional as well so we'll add the two optional parameters at the end of our user model and we'll close the file up now it's not complaining we put this elvis operator here in case it's not defined and if that that's returning a string so if we want to return a boolean we can use the double exclamation mark first exclamation mark we'll see if it's there or not and the second one will uh convert the type so for example if we if we have um a string here hello and then we say not hello for example if we had a constant variable here const x equals hello if we were to say not x this would be false because that implies that there's no x variable set but there is so since there is we'll do a double so i'll return false now return true and if this was blank okay if that was just const x that means not x would be true and not not x would be false so just converts it to a boolean here and i might change this to does author have image just to make it uh the name more of a boolean uh implied through the name so basically we want to let the full path um be equal to the default path by default so we can say this dot get default full image path however if it meets the check that it does the user does have an image that means we can say okay we want to let the full image path equal to the get full image path name and we want to pass in from the user the user image path and of course we want to use the this here now all we have to do is return a new observable so we can just go ahead and return off of the full image path and that needs to be done in the switch map and that gets rid of the error for us we will need to get the image so we can call some http requests to our server to the end points that we set up earlier in the video so we have this get default image path get full image path these are open on the feed endpoint or the feed part of the route in the feed control i should say so next we want to have the ability to get the user so the user these have these can't be accessed directly because they relate to the logged in user so we need to do say get user image and we can go ahead and we can return this dot http dot get and we can just copy something like this in and we can just call the endpoint that we defined earlier the user and the image and we're going to call this elsewhere so i'll just want to get one image so i don't have to unsubscribe if i use the pipe take one approach and that just gets the user image now i'm going to go ahead and i'm going to copy this down and i'm going to have a method called get user image name and this is going to return an observable with the image name which is a string so we can actually go ahead and we can say we can write that here as well if we want and if we write it here then it's implied that it's going to be that but i just like to put it there anyway we hit the base api url we hit the user controller and then we hit the image name endpoint okay so we're able to get the user endpoint get the image and the image name for the logged in user next i want to have the ability to update the user image path so when we upload a photo we want to be able to change the url that's in our database for that associated user for the image path so we can just say we can update the user image path that of course takes an image path of the string and i might call this image pathway image name ideally you'd want to be consistent with this but i'm just doing it on the fly um it doesn't really matter we'll just call it image path so this is going to return a user and we can go ahead and we can just return and this is where we can use our user stream we can go ahead and pipe into the subject and we can say we just want to take one but what we want to do is we want to just go ahead and map the user that we're going to get back or which is of the type user we get back from our observable stream and we want to just add this image path we want to set the image path for the user to the passed in image path that we get so that way we can change the image path of our user and then everywhere that subscribes to that subject as observable so the stream that will be propagated throughout our application so to do that we need to actively call the next method on that so we can get the next user with the updated image path and that is exactly what we return we just return the user so the final method in this area that we'll need to work with is the actual ability to upload we're able to get our images and update our images but we want to also be able to upload our images so we're going to call have this method here called upload user image and it's going to take some form data so this is going to come we're going to uh implement this on the ui side of things and for us to make the request because it's not json uh that we're passing to the back end we're passing a file we need to associate the file with a form so it's going to have some form data here and we'll come back to this and we implement on the ui so this is going to take an observable and it's just going to have a modified file name that's going to come back to us and what we can do here is we can just go ahead and return and we can just copy this post method here so we're able to copy the post method but we will be expecting this modified file name to be coming back we hit the user upload endpoint and we pass in our form data and these http options relate to json so regular form data does not need a extra parameter here so that's the how you upload or make the api request upload our file so what i might do here is i might just pipe into this observable here and but when we subscribe to it before it gets subscribed to we can just go ahead and tap in and we can use this object destructuring to get the modified file name here and what we'll do is when we upload a user image and only if it's successful will we upload will we update our user so then the image we upload date changes throughout our entire application so we can just say we can let the user well we want it to be equal to pretty much the current user objects the name and all that won't change so we can actually just go ahead and get the value here of that but we just want to amend the image path and that's just going to be amended to the modified file name that we're getting back from our server [Music] so because when we up load our file it's going to be of the the the file name is just going to be whatever we called it and then it gets changed when we upload it onto the server with uuid to a random string but we need that random string back so we can access that image from the backend and display it on our front end so we can just set the user image path to that what we get back from uploading [Music] so we can just go ahead and we can say user and but we want to make that change propagate throughout our application so we call the next user okay now we want to actually upload the image from the user's file system so that file can be attached to this form data so they can send it to the back end so we're going to start in this profile summary component and we're just going to add the ability to click here and upload some input so let's work on that so we want to open up our profile summary component and i also want to open up the template so where we have this image this is where we want to have our ability to upload something so what i'm going to do here is well a file upload it needs to have an input so if i add an input here and i say of the type file and i just save that you see that we get this choose file and then it opens up something here and if you choose something you'll get it in there like that however we want to hide this input and we want to make the input trigger if we click a different element so to do that we can just say well firstly we can hide that input so we can say display none and we'll need to give this a template variable so we can just say okay this is going to be called file upload and when there's some sort of change to this file upload we're going to call a function called on file select and it takes in the event that's able to detect the file that you upload from your or choose from your file system so let's just quickly define that one file type on file select and we'll just do that yeah oops so this is going to take an event and it's not going to return anything so i'm just going to log out selected and now i'm going to return back to our template and now we can add a click event to the iron avatar and we can just say when you click on this we want to call the function relating to the input uh we want to reference the input element so since we've gave it a template variable or file load we can access that dom element in our template here so i can say file upload and we can just go ahead and click that and then when we click that it's like clicking it directly so if you just clicked an input field by default that will open up the file system one thing we might want to add here though just for styling is just to add a pointer here so it just actually looks like it you can click on it so i'm going to go ahead and add this cursor pointer here and now if we look at this here and we click on the image and notice that the console doesn't log anything out it's only after the event has occurred that it logs something out and then it says selected if we click cancel we will also click selected so this is where we want to implement some logic here and only allow the correct types to come in and also check that they are the correct types so we can go to our profile summary component and we can pretty much close this file now so on the file select what we're going to get is we we want the file so we can say we're going to have a file here [Music] and it's going to be of the type file now this is coming from the event target but we want to give it some type so we get some intellisense and type safety and this is just the html input element now the target you can have multiple files but we're just selecting one file so we can just go ahead and access the files in the first position or the zero uh i index in the array and of course if there is no file selected if so if you cancel something like that there's no real need to do anything here so we can just return now we will need to [Music] send some form data through so we need to define our types so let's go ahead and define our types here so right at the top of our class we can say well we're going to have a form which is of the form group and you can bring that in and then on the ng on init this is where we can say this form is equal to new form group and we just want to have a field for the file and that's going to be of the new form control and we'll just pass in null on the ng on the knit and we can just save that and another thing we're going to want to add here is some types because there's going to be certain types that we allow you could put this into another file but since it's only gonna be referenced here for now and i know the scope of this application i'm just going to define it at the top here there's only so much refracting i want to be doing for this uh clone i don't want to turn it into an enterprise application that i'm building everything out as i would um in my professional career or anything like that but if i just make a type for the valid file extensions so i'm going to have the pngs the jpegs and also the other type of jpegs in here so i'm going to duplicate that line down and i'm just going to have a valid mime type and i'm just going to prefix each of these with an image slash and i'm going to go ahead and copy that in so these are the allowed mime types here now i'm going to have in the class i'm going to have some [Music] some details here so i'm going to add the valid file extensions [Music] so valid file extensions and that's just all of the valid file extensions so we could just say an array of those and this is again going to be equal to these and we can just control d the pipe operator and change it with a comma bring this down one get the valid mime types so just plural here get this valid mime type and copy in the all the allowed mime types and doing it this way allows you to you know just simply add some more types here or in a type file if you separate it out and you don't have things all over the place so what we want to do is we want to create um we want to pass in our form data so let's go ahead and start to work on that so we're passing in form data into our api call so on that form data here we can just go ahead and append for that file that we just created on the form group you can pass for that file you can pass the file we're getting in and we're getting a file at this stage because it's made it past the no file check so from here this is where we want to actually check the file type and you could just check the mime type and you could do that without a third party package but i've installed file type so i can actually if someone adds that for example that text file that's renamed to png i can actually detect for that and then not even allow it to make the request so i've set that up on the back end as well but i'm going to do it on the front end as well and then things are extra secure so only the types that i want to allow in will get in but for that it uses this file type package here and it's a very very popular package as you can see 20 million weekly downloads however it isn't for angular it's a more general type script sort of package and i believe because angular it um [Music] it compiles the code down such that it can be used on older browsers and whatnot um the typing um some of the methods that are in this file type package don't easily translate over to those older browsers so that means we need to add some poly fills and polyfills is what you do when you need to support for older browsers so if you open up the polyfills typescript file we're going to go ahead and make a global type for us here and we need the buffer type because we're going to use a method in our browser here relating to the buffer by default it's got this from stream and from blob but elsewhere in the package they got the buffer and you can see it implemented in node and this package does focus on the back end side of things so you do have to tweak things a little bit in your single page applications but essentially we want to use this from buffer and there's a particular type of the buffer that we use but if we use the one that's given to us in angular will get an error so this is where we add our global type here and firstly we can just say window as any just so there's no complaints about the type and we can just say for the global variables we'll just set that equal to the window so that means the window dot buffer is going to be equal to the window buffer or we can require buffer dot buffer and notice how this errors well we can just add some uh we can just ignore that so we can just add ts ignore it's like a linting rule or just ignore the type script and just go ahead and ignore that so make sure you do that if you want to be using this file type buffer in your application in angular otherwise it won't work [Music] so if we return to our profile summary that means we want to call a method um called arraybuffer so on our file we want to buffer it to an array which turns it into a blob or it's a type of blob an array buffer now this array buffer this should be this is built in but it's returning a uh promise so we just want to make it an observable so let's wrap that and we can bring the from observable in so what we'll do here is before we get that back we can just pipe into something here and that means we're able to get the return buffer that it's returning for us so we can use the switch map operator to return our own observable and this is where the tight buffer type comes in handy so this is coming from the what we just said before and we're going to need to bring switch map operator in from our express operators now this returns another if we use this from buffer method this is this is what's coming from the package so file type has this from buffer method here and we want to take that from file type slash core make sure you get the right type there so if we return back to our from buffer method this doesn't happen instantly so let's think about what's happening here we're choosing a file and from the file that we've chosen from our file system it needs to convert the file which is an image which basically at its core uh you know if you break it down to its core pieces it's just a really really long string like a blob and um it's in a buffer so a big long but we've got to convert the buffer into something that we can read so what we want to do is call this from buffer method and we can just pass in our buffer that we've got from the built-in array buffer however this is an asynchronous operation so once again we want to wrap this in a from to convert it into an observable then we can pipe into this observable and we can call the switch map operator [Music] and what we're going to get back here and this is built into the package is something called the file type result and this is of the type file type result and we can bring that in and if you want to have a look at what that is essentially well we need to look at the next level in it's essentially it's just got an extension and a mime type and we've seen this before where you get an object back with the extension and with the mime type and what we want to do is check if it matches our extension or mime type so we can close those there so what we'll do here is we'll say well what happens if we pass in that text file that says png what the type that it'll come back with is undefined so since it doesn't recognize the type it will be undefined so we need to have a check here for that so if there's no file type result what we'll do and it's only airing because we're not returning something just yet but that will go away and i'm just going to do a console log here just for now we'll come back to this when we do error handling but i'm just going to have a message here uh saying i want to log out an error and i'm going to say file format not supported and we need to return something so we'll just return an empty observable and that will essentially do nothing so if it makes it past this check it means you know there was a file type so we want to get the extension type and the mime type so we can use object destructuring to get that from the file type result and we can have a method here saying or a boolean statement to see if the file type is legit and we can tell because we've got our valid extensions which is the array of valid file extensions and if our file extension that we get back after it's made it through the file type method returns something that is in our valid file extensions and it's legit but if it doesn't then it's not legit so that extension type that we're getting back now there's a conflict here because of types because the extension you're getting back it doesn't have to be a one that i've defined you get anything back really or undefined so i'm just going to go ahead and since you can get anything back it's okay if you just go ahead and say as any in this particular case and we also want to do a similar thing but for the mime type now i may be a little bit overkill to be checking both but if you want things secure you may as well it's only an extra line of code and we can say if the valid mime types includes the mime pipe that we get back after the file has been processed and checks for its magic number in which the package is able to tell through the buffering of the file whether or not the type is legit or not or it matches that of what we've allowed in that will help us determine if the file type and mime type is legit now we want to have a overall boolean value to see if the file is legit and the boolean is implied both through the name and through type inference so this is just going to be true if both the file type and also the mime type return true if the um file is not legit this is where we're going to have another error handling case that we'll work on in another video um however i might put a more serious error message here file format does not match file extension so we're protecting it on the front end and it's also protected on the back end so we wouldn't even expect to get a back-end log um so we want to be keeping an eye out uh for if we do see the equivalent message on the back inside of things that would be of concern um however the security is set up so that that should not be happening um so okay now if it makes it past all these checks the file is legit the valid file it's the right type we can go ahead and we can just go ahead and return from our off service from the upload user image we can pass in that form data that's going to be passed into our auth service here which makes the http request with that file associated with it and then we get back a modified file name if we need it in which we do because we pipe into that and we tap into it and then we set the next user and the user's modifier image path based on that modified file name that we get back and then that since we have a ability to get our requests um our images we can use that path and return all of our images and propagate the changes throughout all the subscriptions within our application so that just means if you've done all this and you're not getting back which can happen and it will happen and that's just because we're not subscribing to the observable so that should sort things out now one last thing i'll do to finish off this method is i'll just go ahead and blow this subscribe here i'm just going to say this form dot reset now it's not super serious in this particular case because we have a image file and you literally need to click onto the file system and off it for you to even get into this method and then the file will be attached to the form but it just clears that from the form and if you were to have some multi-form data like you had some things that you typed in text and then the image as well then it'll just clear all that as well for you so it's a nice touch to use that and this is only airing because we're not returning it so let's go ahead and return this observable here we can save that and with that we've pretty much set up our user image upload functionality now let's go ahead and try it out although the changes won't happen yet because we haven't subscribed to them but let's just go ahead and see if we can do that and would expect to in the back end in our images for something to happen so click on this i'm just going to get this nest image here now did anything happen well we can see that it did upload it to our server for us so that's awesome so and also i should probably look at the database here there's nothing here in the user but if we refresh this we do get that file name in there so that's awesome so now what we need to do is subscribe to that to the stream of user and get the image throughout our application and that's relatively easily from here so let's just go to the top and we while we're doing this we should probably do the full name as well i'm not going to make everything dynamic like the full stack developer and all that sort of things just doing it so we know how to do it if we were to be doing this so let's go ahead and just get that subscription that we're interested in so what are we interested in we're interested in the let's see here the full image path for the user so we'll create a variable use a full image path this is a string now we want to have a subscription because recall that we have access to our user stream and we want to subscribe to this and detect any changes to the user subject and propagate that through our app and we'll do this in the profile summary component to start things off so the auth service this is our source our stream our dynamic source of our user that can change and we subscribe to it and if it gets updated then it will be changed throughout so what we'll do here is we'll have a private user subscription which is of the type subscription and the reason i do this is because i want to also be able to unsubscribe so and we'll see that in a moment so if i go to the ng on a net we can go ahead and say okay this dot user subscription is equal to the all service dot um so this is where we want to get the user full image path so if we look at that we get this that get method we made here and this is going to either get us the default image or the uh full image path so and what we're expecting back is just the string that that gives back so this user subscription this is going to be equal to that image path there and we're not go we don't need to do a pipe one take one here because we're going to unsubscribe to this so we get the full image path that's going to be the string we say this dot user full image path we set the variable to the full image path so as long as we're subscribed it will constantly update the user full image path so since it's doing that what we want to do is we want to unsubscribe if we need to so that means here [Music] we can have an on destroy and we can bring that in which is complaining because we do not have a ng on destroy life cycle method but we can very easily call that user subscription and unsubscribe from it so alls we really need to do now that we subscribe to that is to [Music] change the source of the html such that rather than getting a hard coded value we can just go ahead and we can just say well if there is some sort of um what did we call it use a full image path if that's there we can go ahead and show an image and it should always be there because if it's not there we'll show the um you know the other the the no image image the placeholder uh but you know just in case you deleted that file or something like that um so yeah okay so we're gonna have to log in again so log into the user that has a image and it's showing that it does not have an image so what about if i choose this image again okay so it's still showing that it's not having an image so it is doing something just not exactly what we wanted so what i'm going to do here is i'm just going to go ahead and put a console log in here and i'm going to put in the full image path but i also want to try out the username as well so recall that we have the ability to get the user full name and let's go ahead and do that so let's do that below here so we get a full name and this is going to be an observable and we'll set this to a new behavior subject so we can push changes to this and we'll set that to be null and then we'll also have a full name and then we'll just set that equal to blank so we'll bring this in behavior oh there's no r so we can bring this in and save that and then we can go to our ng on a net and before we do this user subscription here we can say this dot off service and then we can get our user full name that's getting the user full name and we can pop into that so we pipe into it so we can use the take one uh i try and use the take one where you call it rather than defined in the service unless it's tricky not to do it um so it's good to remember where you're calling it that um you know you're just taking one and then you go ahead and get the full name which is going to be your string [Music] and then you go ahead and get back then this is where you set this full name equal to full name and this is where we can actively call the change to the full name so the full name observable or subject which is a observable that you can call the next method on and then you can just pass in the full name here and with that we should be able to get the full name now obviously we're not changing our name um so we're changing the image but if you were to have the ability to change your name then where we subscribe to there it should change when you update the user so one thing i'll note is that if i upload an image i am not getting my console log which means it's probably not making it to that section of the code so i'm going to go ahead and find the bug so the reason for the error is actually coming from the back end side of things we were expecting an object with the modified nut file name to be coming back but right now we're just getting update result so rather than getting an update result or an error we would actually like to get our modified file name because the if the file name is not coming back for the location on the server then it's not going to change the on the front end to point towards that file so let's just go ahead and get that now we're getting some errors going on here this can be alleviated by just going into this switch map here and update user image by id now we check if the file's legit on the back end as well we get the user and then we update the user image by id so this is where we can actually pipe into this observable here and we can just go ahead and we can map so rather than getting our update result back we can it doesn't really matter what we get there but what we want to pass back is this object with the modified so we can add this here and because we've returned this object within the parentheses this will just mean or return and we want the file file name that we're getting back from here go ahead and save that and it's just complaining here because it's it's a uh expecting an observable back so rather than using map let's just go ahead and use switch map and let's go ahead and wrap this whole thing an observable and then now let's save that so let's try and refresh our page and let's try and upload something and there we go we see that that has been updated and if we to refresh we see that it's not persisting right now but it's still letting us select the thing so let's continue to work on the logic here so what we've done here is when we open the profile summary component this is where we actually call the subscription to subscribe to the user and i've just console logged the full image path here as one and you notice that we're getting this blank profile picture now that might seem a little confusing and it isn't set up correctly just yet because we've there is a actual image that we've uploaded and that's being set to the user but the reason it's saying that it's not set is because we haven't updated the ui and module on the client so basically nowhere in this application are we doing our first and i can remove this now but actually i'll leave it there just for now but we're not actually getting the user image so nowhere in this application how we hit the endpoint to get our user image in the first instance so we want to get that user image and actually we want to get the user image name so then we can put into the html so for that and then we need to call in a logical place and because we're going to have an image in a few places it doesn't really make sense for it to be in the profile summary component although technically it will work and but it we should put it somewhere more um it can be a source to the other places so a good place to have that would be in the post service because that's injected into the main section here and then they'll cause the next to propagate for that user so we need to get it in the first place basically and be aware of that in our application in our application so if we open up the post service uh let's see here in home in services we've got the post service here so a good place to do this would be in the constructor so let's go ahead and do that so let's just say we want to call this auth service and of course we need to inject that so we have it and one thing to note is um the auth section is sort of going to be needed throughout the application so it could be in a shared uh section uh so it doesn't really matter if we're using all our modules right now we've only got this other you know this post feed module um but it's all good so this is of the type auth service we'll bring this in and you could put this in a on a knit um and typically you would but i don't really need it for anything else and i want this to happen at the beginning so it doesn't really matter of course if you have your preferences you can do that so there is the get user image name so we want that we want that to be running first and we can just pop into that and that will allow us to just take one because we only need it in the first instance when the page loads and otherwise the image name is going to be updated as it is called uh here in our subscription here [Music] so and when we call the next user image name basically what we want to do here is we just want to tap into this and we know that we're going to get the image name back and we can use object d structuring to get the image name out of the object and if there is an image name and i'll bring in tap if there is an image name what we'll do here is we'll once again call the auth service and then we'll call the update user image path and we'll pass in the image name so we want to [Music] call the call like we want to set it basically to the initial from the initial load set it to the user and we subscribe to that so it should be propagated to where we've subscribed to it so we pass in the image name and then we go ahead and we just subscribe to that and because we have used the take one over here we can just subscribe to them not have to worry about any memory leaks but if there is not an image name this is where we would want to call our default image so basically our default image [Music] and we can just use that method we made before get um and actually we might just pass in this bit here so we'll do a little bit differently and that's because the update user image path it takes the image path in here like this and then it sets it like that so we don't want the full thing we just want the name so what we'll do here is we'll just say blank profile picture png and we'll go ahead and we'll call this auth service so then we're able to update the image path based on that default image path instead and then we can go ahead and subscribe to that and if you want you could just if you have a name um you don't have a name you set the path here and then you just have the one subscription uh and in fact let's just go ahead and do that just make it slightly cleaner so if there's uh no image name actually it doesn't really matter that much um actually i may as well it's pretty easy to do so basically what i want to do is i want to say if there's no image name change this and we have no there's no need for an else anymore we can just go ahead and put this in here like this and we could have the image name or the default image path which actually means we don't even need this if check because if it's not there or just use the default image path so let's go ahead and get rid of these lines here and we've simplified our code a little bit here okay so we've got the user image name and we're updating it so now this isn't going to fire because we haven't subscribed to the outer observable meaning everything inside it won't be working so what i'm going to do here is i'm just going to go ahead and subscribe so let's see if that works and you may have spotted that i have not used this get user image name so we can go ahead and just pass in our image name here actually sorry let's go ahead and log out our image name here just to make sure we're getting the right thing and i'll just also log out a 33 so we can find the comment or the log so we can see that this actually isn't even firing and i found the root of the problem before we'll i changed this to a switch map because the map wasn't working but the reason the map wasn't working is because i wasn't importing the map from rxjs so this is in the user controller on the back end now that i'm mapping to the modified file name i should finally be able to get the file name so let's go in here now let's return to where we've commented out in our post service now i was just doing some debugging here but we can go ahead and we can remove this now and we can bring back our method and we can save that so with a little bit of debugging i just found that this image name i just had some slight typos in it and basically what we want to do is it's very similar to the previous one we go ahead and we just use the guard jwt we get the end route image name we give it a name find user image name and we pass in the request but the reason why it wasn't working is was waiting to give back a response and that's where this res things was coming from and that was holding things up so basically if i just get rid of this res here i'll be able to get back my image that i have and before it was just permanently hanging and i was just waiting for that request and i can go ahead and get rid of this comment too so with that finally we're able to get our image as it is in our profile so if i change this to this image it gets changed and if i refresh then it stays there so that's awesome so we've finally got things working now i can return back to the code i can close the back end up again and i can go to the post service and i can go ahead and delete my debugging work and basically where we're at is this post service is going to run because it's injected into the main page and that's a perfect time to start the core to get the initial user image and we get the image and if it's there or we pass it in if not we give back a blank profile so we can update the user to that blank profile picture and then we go ahead and subscribe to both of those and that will make our change stay here so what i want to do next is i want to update all of the different areas so this would be more or less the same sort of thing so let's just take a look at the process that we have here so in the profile summary component this is where we can get rid of this debugging now this is where we have our subscription to our user object and we go ahead and we for our user subscription we define a variable for that subscription so we can unsubscribe to it when the component gets destroyed so we're able to subscribe here and i might even call this user image path subscription not to get confused with the user subscription so let's go ahead and change this to user image path subscription it's a long name but it's quite descriptive and if i go ahead and change that there and also in the on destroy method so let's begin to replicate this for the start post component and our other components and we can see that we're going to need the name in here and also in the in the two pop-ups and modals the pop-over in the mode we're going to need the name in addition to that and we've set that up here so this start one start post component this is where we'll just copy the logic more or less so i'll just do a control p to open up the start post component i'm going to go ahead i'm going to copy the user image full path and the subscription and i'm going to define those variables at the top of the class i'm going to bring in subscription from rxjs and i'm going to go to the ng on init i'm also going to implement ondestroy so i can under subscribe so i'm not getting any memory leaks so i can just go to the ng on init i can copy over the user image path subscription here into our and i'm going to need the auth service so i'll get that in as well so the user image path subscription is equal to the auth service and subscribing to that event as before and then we're just going to need the other life cycle method to get the ing on destroy and then we can just simply call this user subscription and we can unsubscribe so all we need to do is show these changes in our template so for our iron image we can just say if we have a user full image path we can go ahead and use that and then we can bind that to that path and now if we take a look okay if i change this to a different logo we see that it changes here as well so we're doing well and if i refresh the change will stay so let's just keep going we'll do the same thing in the modal component so let's bring that up and we'll also get up the template so we'll just copy those over bring into the modal we will get our off service we'll bring in the subscription and we're starting to see a little bit of a pattern here get the ng on destroy as well so we're able to implement the ondestroy interface and of course we can do the logic in the ng on init and we can copy the same thing over to this image over here too so we'll look for the iron image and we can just go ahead and we can place this here like this and we can get rid of this and i just realized we may actually want this on the avatar um although an empty avatar doesn't really matter so we'll just keep going like this and we see it there so we're nearly done we just got two more to do so let's open up the header and the html exact same steps copy this over find the variables at the top here bring in the subscription implement the on destroy lifecycle method go to the end of the file the control end put it at the end call on i destroy to import that do this in the ng on a nit and you can see how we're subscribing in all these places to a source so if the source changes then all of the places where it subscribe to changes and that's quite helpful especially if we change up the logic we don't have to change it in multiple places or anything like that so we'll just bring in that auth service there and we'll just copy this thing here again get the image search for the iron image okay i'm not seeing an image for some reason oh iron dot img get this bind it we see it there and now finally we just need the [Music] uh profile image to be changed for the popover so we'll get that and that's in the popover component so let's go ahead and we'll just say okay so the popover component will copy over the we'll get the all service to the popover component and just ignore those errors there oh we already got it so we'll go ahead and get those variables in there so let's get those bring in subscription get beyond destroy unsubscribe subscribe where necessary in the ng on a net and we see we'll do this here now what we can do is we can say ng on on the net we'll get the full image path we'll bind that to the iron image and we'll place that here so save that okay we're getting some sort of weird error here so we'll just go ahead and remove the ng if save that and there we go and if we were to choose another image let's say this one we can see that that change has propagated all throughout our code base so i just need to change this name here as well now currently looks the same but it's just hard coded at the moment so i might go ahead and do that so how i'll do that is i will go back to my profile summary because that's where i've done another full name for that profile summary component so i can actually just go ahead and i can just copy these in copy these over to the pop over command i'm not sure why it's airing right now but i'll deal with that in another video in their handling or something like that um still want to this video is quite long and i want to stay focused on the image upload so i'm just going to go here
Info
Channel: Jon Peppinck
Views: 145
Rating: 5 out of 5
Keywords: angular, ionic angular, ionic 5 angular, ionic, ionic 4 angular, ionic framework, ionic 5, ionic 5 tutorial, learn ionic 5, ionic for beginners, angular 5, ionic course, ionic 4, ionic 5 for beginners, ionic 5 course, angular tutorial, angular 7, ionic tutorial, angular 2, angular 7 tutorial, learn ionic 4, image upload, angular file upload, angular 8 file upload, file upload, angular 8 upload image, ionic image upload, angular 9, angular 4, ionic 4 tutorial
Id: NT6LiHTdkBw
Channel Id: undefined
Length: 98min 25sec (5905 seconds)
Published: Mon Jun 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.