Updated 057 Drag and Drop Upload functionality in JCB (markdown)

Amigo 2019-09-25 11:23:10 +02:00
parent 65dee0d8c5
commit 415e1c1e09

@ -207,15 +207,18 @@ If you don't know what that is, let me quickly show you. In the component it has
[00:57:45](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h57m45s)
Here is the 'uploadFile'function. The 'uploadFile' starts by first getting the view ID and checks it. Then making sure that there is a view set and that view is part of the '`allowedViews`' array. The 'allowedViews' array, if you remember [00:58:08](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h58m08s) the '`allowedViews`' is documents. That is why I am setting that outside the custom code, because it depends on which component we are working in. If it is an 'allowedView', we then get the target, and the type and we set it to Global target in Global target type. [00:58:45](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h58m45s) Then we check that this type that is the format that has been mentioned. That is the formats that we allow, the types, because we need to anticipate what a person is going to upload and to validate that. [00:59:17](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h59m17s) It is setting the `format` with the `type`. If it is `image` it will be `images`. If it is `images` it will be `image`. If it is `document` it will be `documents`, if it is `documents` it will be `document`, and `media` will be `media`. That is the types and we are setting that as the `formatType`.
Here is the 'uploadFile'function. The 'uploadFile' starts by first getting the view ID and checks it. Then making sure that there is a view set and that view is part of the '`allowedViews`' array. The 'allowedViews' array, if you remember [00:58:08](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h58m08s) the '`allowedViews`' is documents. That is why I am setting that outside the custom code, because it depends on which component we are working in. If it is an 'allowedView', we then get the target, and the type and we set it to Global target in Global target type. [00:58:45](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h58m45s) Then we check that this type that is the format that has been mentioned. That is the formats that we allow, the types, because we need to anticipate what a person is going to upload and to validate that. [00:59:17](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h59m17s) It is setting the `format` with the `type`. If it is `image` it will be `images`. If it is `images` it will be `image`. If it is `document` it will be `documents` if it is `documents` it will be `document`, and `media` will be `media`. That is the types and we are setting that as the `formatType`.
### GetPackage From Upload
[00:59:41](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=00h59m41s)
Then we are using a function `getPackageFromUpload`. If you watched the previous tutorial on using the 'File type uploader', It is more or less the same kind of function. If I scroll down to, `getPackageFromUpload`.[01:00:02](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h00m02s) The only differences we are doing the `getApplication` and the input in the function. We are targeting files because we are passing those values in the file's place. We are seeing what is the file. We are checking whether these things are allowed: `warning, import file error`. This kind of error is not thrown to Joomla, it is added to the error message. [01:00:35](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h00m35s) Because we have to give it back to the view. This is a Ajax call, nobody will see it if we just use the array's warning. So we are actually grabbing the value and say we are done here get out of here, if we are still going and you could go through this and it has very much the same implementation than the one we have demonstrated. The only difference though is our check method. It takes that view and again validates it.[01:01:12](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h01m12s) An 2nd layer of validation is done and then it gets checked whether this specific user that is now logged in has the right to edit this item. It is doing some user validation. If not, it removes the archive. We still have that remove method with a little bit of the code that you saw me take out, that is still left in. In the previous tutorial I used some of these codes. That is all very much the same, I will not go into depth. If you do not understand this watch the previous tutorial.
Then we are using a function `getPackageFromUpload`. If you watched the previous tutorial on using the 'File type uploader', It is more or less the same kind of function. If I scroll down to, `getPackageFromUpload`.[01:00:02](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h00m02s) The only differences we are doing the `getApplication` and the input in the function. We are targeting files because we are passing those values in the file's place. We are seeing what is the file. We are checking whether these things are allowed: `warning, import file error`. This kind of error is not thrown to Joomla, it is added to the error message. [01:00:35](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h00m35s) Because we have to give it back to the view. This is an Ajax call, nobody will see it if we just use the array's warning. So we are actually grabbing the value and say we are done here get out of here if we are still going and you could go through this and it has very much the same implementation than the one we have demonstrated. The only difference though is our check method. It takes that view and again validates it. [01:01:12](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h01m12s) The 2nd layer of validation is done and then it gets checked whether this specific user that is now logged in has the right to edit this item. It is doing some user validation. If not, it removes the archive. We still have that remove method with a little bit of the code that you saw me take out, that is still left in. In the previous tutorial, I used some of these codes. That is all very much the same, I will not go into depth. If you do not understand this watch the previous tutorial.
In our upload file, we at this point have the package. We pass the package to `uploadNow`. Now move the file into place. Remember we had to do that here and a `uploadNow` function is used. In the `uploadNow` function, we `return` and if any error still remains, it is going to be dealt with here. Whereas errors that might have occurred here, if this was false, we would use that. [01:02:36](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h02m36s) That is the error message, put it in error and pass it out. If there are any other issues, we will see there has been an error and will pass it out, there is this error handling there. <<<<<<<<<<<<
In our upload file we at this point have the package. We pass the package to `uploadNow`. Now move the file into place. Remember we had to do that here and a `uploadNow` function is used. In the `uploadNow` function, we `return` and if any error still remains, it is going to be dealt with here. Whereas errors that might have a occurred here, if this was false, we would use that. [01:02:36](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h02m36s) That is the error message, put it in error and pass it out. If there are any other issues, we will seen there has been an error and will pass it out, there is this error handling there. <<<<<<<<<<<<
@ -223,43 +226,43 @@ In our upload file we at this point have the package. We pass the package to `up
[01:02:48](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h02m48s)
Now in uploadPackage, we are checking whether the package is there, the package name and we're starting from that, we are building the name. Now remember I showed you or explain to you that we are using and preserving the filename but we are hiding the filename. We are using the targetType the fileFormat and then this randomkey generator. [01:03:17](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h03m17s) Now I'm not exactly sure I think all JCB helper classes comes out with this randomkey. You could just use it in your component and you can decide how long this string should be. Then I'm using a little placeholder which is little generic placeholder VDM. I'm adding the actual name of the file after this placeholder that everything before this placeholder is really internal, my system uses this, but the client uses everything this side. If it's a document [01:03:56](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h03m56s) we are going to need the folderpath for hiddenFilePath. Again getFolderPath is a function which I wrote. I'm not going to share that with you, but you can build your own helper class function to get the path to where you want to put the file, this is up to you. I'm using a hiddenfilepath, but there is a lot of discussion behind that. If I don't pass any values like in this case, [01:04:28](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h04m28s) it most probably return a public path. It would be where the images go. Every documents go in a hidden area, images go public. Usually the image you wanted to load somewhere, you don't want it to be behind the root folder of your website.
Now in uploadPackage, we are checking whether the package is there, the package name and we're starting from that, we are building the name. Now, remember I showed you or explain to you that we are using and preserving the filename but we are hiding the filename. We are using the targetType the fileFormat and then this randomkey generator. [01:03:17](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h03m17s) Now I'm not exactly sure I think all JCB helper classes comes out with this randomkey. You could just use it in your component and you can decide how long this string should be. Then I'm using a little placeholder which is little generic placeholder VDM. I'm adding the actual name of the file after this placeholder that everything before this placeholder is really internal, my system uses this, but the client uses everything this side. If it's a document [01:03:56](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h03m56s) we are going to need the folderpath for hiddenFilePath. Again getFolderPath is a function that I wrote. I'm not going to share that with you, but you can build your own helper class function to get the path to where you want to put the file, this is up to you. I'm using a hiddenfilepath, but there is a lot of discussion behind that. If I don't pass any values like in this case, [01:04:28](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h04m28s) it most probably returns a public path. It would be where the images go. Every document go in a hidden area, images go public. Usually, the image you wanted to load somewhere, you don't want it to be behind the root folder of your website.
### FullPath - FilePath - FileName - FileFormat
[01:04:46](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h04m46s)
We end up here with the fullPath which is the filePath and the fileName and the fileFormat. That becomes the fileName and this becomes the fileFormat. You will notice that at this stage the packagename is what it's used to build this name. We are stripping the fileFormat from that packagename making sure [01:05:19](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h05m19s) that it doesn't have a fileFormat in it. To ensure that this file is stored in exactly the format, we detected as and not as what I said it is. We move the package. This is where it gets interesting to its final destination. If something fails at this point like it doesn't move, [01:05:45](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h05m45s) we remove the package and we say there was an error. We are done. We are not going to worry about it. If it succeeds then if it's an image, at this stage image, we definitely want to resize it. I've a resize image helper Class. This is also something that you would need to write yourself. [01:06:12](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h06m12s) It helps me to resize my image. I am passing it some values to target the image and resize it. It doesn't change anything with the image location or anything like that, I don't need any value back, I just need it to resize it and get it done. I don't need to know anything else.
We end up here with the fullPath which is the filePath and the fileName and the fileFormat. That becomes the fileName and this becomes the fileFormat. You will notice that at this stage the packagename is what it's used to build this name. We are stripping the fileFormat from that packagename making sure [01:05:19](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h05m19s) that it doesn't have a fileFormat in it. To ensure that this file is stored in exactly the format, we detected as and not as what I said it is. We move the package. This is where it gets interesting to its final destination. If something fails at this point like it doesn't move, [01:05:45](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h05m45s) we remove the package and we say there was an error. We are done. We are not going to worry about it. If it succeeds then if it's an image, at this stage image, we definitely want to resize it. I have a resize image helper Class. This is also something that you would need to write yourself. [01:06:12](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h06m12s) It helps me to resize my image. I am passing it some values to target the image and resize it. It doesn't change anything with the image location or anything like that, I don't need any value back, I just need it to resize it and get it done. I don't need to know anything else.
### Encryption
[01:06:35](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h06m35s)
I'm doing some encryption to see whether the basic encryption is available in this program. To use that encryption, when I start storing the documents to the database. Here is a local file, and we are checking if it's a document or a media. We are going to encrypt it. Again here we make sure that this ID value [01:07:04](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h07m04s) is greater than zero. Because if it's still a unsaved item, we don't have any place in the database to add this. We could skip this. If we realize this file or this Upload doesn't have an ID, then we skip this function, and we rather do an image. If it's a document or if it's a media, [01:07:29](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h07m29s) then we load the filename. We are going to pass it back to the view, taking the results as you see here formats, it's got a 'lock' value and a 'token' and [01:07:46](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h07m46s) 'link'. It has different behavior for different things. It all builds this result array and this is what we give them back. It gets started over here(see video). The fileformat is added, success, gets the filename which is this value here. Then we start building some other things which are necessary. [01:08:10](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h08m10s) Like the 'tokenLink' for the 'link'. Because you want to have it downloadable, if it is media or document. If it's an image, we don't need any of this. We can skip that. Then the 'keyName'. We are done. Where as it is a safe item, we are going to update the database, [01:08:35](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h08m35s) with this new 'targetType' and 'target'.
I'm doing some encryption to see whether the basic encryption is available in this program. To use that encryption, when I start storing the documents to the database. Here is a local file, and we are checking if it's a document or a media. We are going to encrypt it. Again here we make sure that this ID value [01:07:04](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h07m04s) is greater than zero. Because if it's still an unsaved item, we don't have any place in the database to add this. We could skip this. If we realize this file or this Upload doesn't have an ID, then we skip this function, and we rather do an image. If it's a document or if it's a media, [01:07:29](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h07m29s) then we load the filename. We are going to pass it back to the view, taking the results as you see here formats, it's got a 'lock' value and a 'token' and [01:07:46](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h07m46s) 'link'. It has different behavior for different things. It all builds this result array and this is what we give them back. It gets started over here(see video). The fileformat is added, success gets the filename which is this value here. Then we start building some other things which are necessary. [01:08:10](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h08m10s) Like the 'tokenLink' for the 'link'. Because you want to have it downloadable, if it is media or document. If it's an image, we don't need any of this. We can skip that. Then the 'keyName'. We are done. Where as it is a safe item, we are going to update the database, [01:08:35](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h08m35s) with this new 'targetType' and 'target'.
### Convention In The Hidden Field Name
[01:08:39](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h08m39s)
This is where the hidden field name, remember I said to you there's some convention in the hidden field name. Well this is where that convention comes into to play. The hidden field name is build up from 'target' and 'targetType'. If these two are not correct we are not going to save this value at all. We are building an object which we will take, since we have validated that this is definitely the allowed view, and this object and ID, then we update the database. We're done. [01:09:13](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h09m13s) We've the 'fileName' and we are going to pass the 'fileName' here in the same way, and return to the browser. That's the service side of this implementation. There are some things which I haven't explained. Like [01:09:33](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h09m33s) this resizing of the image. I didn't give much explanation. 'GetFolderPath' you don't need to write that all up. You could make this work without knowing those things. [01:09:48](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h09m48s) You could put a hardcoded path here as the filePath. You will not have to do any cropping, let the user make sure about the cropping. [01:10:01](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h10m01s) That is how I upload many of my documents and things. This is constantly improving, because I'm using the snippet across multiple places. It's very easy for me to come in here and say oh this is not [01:10:17](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h10m17s) ideal and then fix it. Then I it fix it everywhere for every place it's been used. There is sometimes the need of decoupling some of these functions in some, but I'm trying to do as much as I can to not to that.
This is where the hidden field name, remember I said to you there's some convention in the hidden field name. Well, this is where that convention comes into play. The hidden field name is build up from 'target' and 'targetType'. If these two are not correct we are not going to save this value at all. We are building an object which we will take, since we have validated that this is definitely the allowed view, and this object and ID, then we update the database. We're done. [01:09:13](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h09m13s) We have the 'fileName' and we are going to pass the 'fileName' here in the same way, and return to the browser. That's the service side of this implementation. There are some things which I haven't explained. Like [01:09:33](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h09m33s) this resizing of the image. I didn't give much explanation. 'GetFolderPath' you don't need to write that all up. You could make this work without knowing those things. [01:09:48](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h09m48s) You could put a hardcoded path here as the filePath. You will not have to do any cropping, let the user make sure about the cropping. [01:10:01](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h10m01s) That is how I upload many of my documents and things. This is constantly improving because I'm using the snippet across multiple places. It's very easy for me to come in here and say oh this is not [01:10:17](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h10m17s) ideal and then fix it. Then I fix it everywhere for every place it's been used. There is sometimes the need for decoupling some of these functions in some, but I'm trying to do as much as I can to not to that.
### SetFileNameArray - Another Function
[01:10:47](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h10m47s)
'setFileNameArray' is another function that you saw in the upload where is it 'setFileNameArray'. This 'setFileNameArray' is a key, when you realize that the actual file already exists because the ID is there. That means that there are other files possibly still already in the database. With the add and basic view, we trigger the 'setFileNameArray' function to check the database [01:11:16](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h11m16s) for that specific target field, get the values, encrypt them, load new values to that and then pass it back to us. Where if the item doesn't exist, that means it doesn't have an ID, I don't know if you remember when we [01:11:35](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h11m35s) did some demonstration, I was adding multiple media files that only one ended up being remembered, that is sort of the downside of the current implementation. If the ID doesn't exist, we're not able to keep track of that. [01:11:55](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h11m55s) It's only when the ID exist, that we are able to do multiple uploads at once.
'setFileNameArray' is another function that you saw in the upload where is it 'setFileNameArray'. This 'setFileNameArray' is key when you realize that the actual file already exists because the ID is there. That means that there are other files possibly still already in the database. With the add and basic view, we trigger the 'setFileNameArray' function to check the database [01:11:16](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h11m16s) for that specific target field, get the values, encrypt them, load new values to that and then pass it back to us. Where if the item doesn't exist, that means it doesn't have an ID, I don't know if you remember when we [01:11:35](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h11m35s) did some demonstration, I was adding multiple media files that only one ended up being remembered, that is sort of the downside of the current implementation. If the ID doesn't exist, we're not able to keep track of that. [01:11:55](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h11m55s) It's only when the ID exists, that we are able to do multiple uploads at once.
### Heads Up - Once Saved The Item - Ready To Allow Multiple
[01:12:03](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h12m03s)
I should give a little bit heads up about that. Once you have save the item, you're ready to expand upon it and to allow multiple upload at once. The 'setFileNameArray' is dealing when you are having multiple. You'll see there is image and document. When the file I'm using is plural, it tells me that it should allow multiple. [01:12:32](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h12m32s) If it's singular, image and document, then I don't allow multiple. I'm just going to remove the old one, and add the new, done. When it is plural, we are using the 'setFileNameArray', and we are building it to be multiple.
I should give a little bit heads up about that. Once you have saved the item, you're ready to expand upon it and to allow multiple upload at once. The 'setFileNameArray' is dealing when you are having multiple. You'll see there are image and document. When the file I'm using is plural, it tells me that it should allow multiple. [01:12:32](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h12m32s) If it's singular, image and document, then I don't allow multiple. I'm just going to remove the old one, and add the new, done. When it is plural, we are using the 'setFileNameArray', and we are building it to be multiple.
### 'removeFile' - Some Point Do Validation
[01:12:53](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h12m53s)
One thing I didn't emphasize here, is that we remove the files as well. There is a 'removeFile'. It also at some point does a validation to check whether the user has the permission to remove files. It will remove the file. It's also uses [01:13:23](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h13m23s) this 'setFileNameArray', but then it passes the remove variable to it. Which then means the action is not to add but to take away. You will see the action and the Add and the take away option. It behaves a little bit different. [01:13:41](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h13m41s) We still get back the array, we still build an object, and we still updated the database, as well as removing the file. All of this code I will dump on GitHub and the gits for you to reuse as you see fit. you'll obviously have to Adapt it, And Keep it under an open source licence. That's Only requirement. [01:14:14](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h14m14s) That if all those things line-up and are in place, going back to our Admin View. 'CUSTOMCODE=phpAjaxUploader' needs to be there. These things need to be here(see video). You could pause the video [01:14:31](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h14m31s) and make sure that you have the same kind of Ajax query calls option. Here I am doing some opening of the files. You will see that I'm building what I have called 'links'. It is going a little beyond showing you a little bit of my implementation and these links eventually end up on the page. We've go back to our JavaScript, and scroll down, we will see this 'getFiledJS'.
One thing I didn't emphasize here, is that we remove the files as well. There is a 'removeFile'. It also at some point does a validation to check whether the user has the permission to remove files. It will remove the file. It's also uses [01:13:23](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h13m23s) this 'setFileNameArray', but then it passes the remove variable to it. Which then means the action is not to add but to take away. You will see the action and the Add and the takeaway option. It behaves a little bit different. [01:13:41](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h13m41s) We still get back the array, we still build an object, and we still updated the database, as well as removing the file. All of this code I will dump on GitHub and the gits for you to reuse as you see fit. you'll obviously have to Adapt it And Keep it under an open-source license. That's the only requirement. [01:14:14](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h14m14s) That if all those things line-up and are in place, going back to our Admin View. 'CUSTOMCODE=phpAjaxUploader' needs to be there. These things need to be here(see video). You could pause the video [01:14:31](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h14m31s) and make sure that you have the same kind of Ajax query calls option. Here I am doing some opening of the files. You will see that I'm building what I have called 'links'. It is going a little beyond showing you a little bit of my implementation and these links eventually end up on the page. We've go back to our JavaScript, and scroll down, we will see this 'getFiledJS'.
### 'getFileJS'
@ -267,4 +270,4 @@ One thing I didn't emphasize here, is that we remove the files as well. There is
Let's again look at that 'getFileJS'. You'll see that those links come in to play. You will see that here I have 'load the links to the page' document links, and I'm adding it to a variable called 'documentLinks'. [01:15:37](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h15m37s) In the Custom script, 'getFileJS' you'll see if I'll take this copy and search, you'll see that I'm using that array and saying, is this property there? [01:16:03](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h16m03s) And then creating a link. That is how we deal with some of that. It works very well, to sort of pass value from JavaScript to PHP, and have it available there.
I know this was a lot of [01:16:22](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h16m22s) things to take in, and I would expect you to realize that the previous implementation is much easier. But like you've seen when someone does create a document, and they are able to easily drag and drop stuff, it crops it and gives your component a much easier feel to it. [01:16:52](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h16m52s) Instead of the old you could still do the old select, but the drag and drop has become quite popular. This implementation is very nice to have. I'm sure from what I've shown you, you should be able to get this going in your component. [01:17:14](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h17m14s) I'm not going to give support on to this, meaning that if you get stuck, you are on your own. You will need to know your JavaScript, and your PHP, and you will need to know how to debug, and how to line-up these concepts that they all [01:17:36](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h17m36s) I work in synergy together. It's not going to be easy for me to do that, especially since I do not see the code. But if there isn't any of the code that I've share on Gits, which I will also put in the description below this video. Even if that code has issues in it, [01:17:57](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h17m57s) or errors that are a very big problem or something. Then please do feel free to give me a heads up over there. We'll collaborate and improve it as necessary. At the end of the day this feature is way behind what [01:18:19](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h18m19s) you really need. There is a media manager in Joomla which is ideal. The advantage about this way, is that your user is never going to interfere with other users documents or images or stuff. If you use this concept, they will not ever going to look on your server at a list and select stuff. This is why I think people would like this, [01:18:43](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h18m43s) because they can upload stuff in and it doesn't affect other people. It doesn't make you more vulnerable as the owner of the system or who uses the application, it is a better approach. But like I said there is a Media Manager. If you go to content, there is a Media Manager, and a media file type which [01:19:07](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h19m07s) works very well, and can also add these kind of functionality to your component, if this is a little bit too a big of a challenge for you.
I know this was a lot of [01:16:22](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h16m22s) things to take in, and I would expect you to realize that the previous implementation is much easier. But like you've seen when someone does create a document, and they are able to easily drag and drop stuff, it crops it and gives your component a much easier feel to it. [01:16:52](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h16m52s) Instead of the old you could still do the old select, but the drag and drop have become quite popular. This implementation is very nice to have. I'm sure from what I've shown you, you should be able to get this going in your component. [01:17:14](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h17m14s) I'm not going to give support on to this, meaning that if you get stuck, you are on your own. You will need to know your JavaScript, and your PHP, and you will need to know how to debug, and how to line-up these concepts that they all [01:17:36](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h17m36s) I work in synergy together. It's not going to be easy for me to do that, especially since I do not see the code. But if there isn't any of the code that I've share on Gits, which I will also put in the description below this video. Even if that code has issues in it, [01:17:57](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h17m57s) or errors that are a very big problem or something. Then please do feel free to give me a heads up over there. We'll collaborate and improve it as necessary. At the end of the day, this feature is way behind what [01:18:19](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h18m19s) you really need. There is a media manager in Joomla which is ideal. The advantage of this way is that your user is never going to interfere with other user documents or images or stuff. If you use this concept, they will not ever go to look on your server at a list and select stuff. This is why I think people would like this, [01:18:43](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h18m43s) because they can upload stuff in and it doesn't affect other people. It doesn't make you more vulnerable as the owner of the system or who uses the application, it is a better approach. But like I said there is a Media Manager. If you go to content, there is a Media Manager and a media file type which [01:19:07](https://www.youtube.com/watch?v=UvzDyVQyHDI&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&t=01h19m07s) works very well, and can also add this kind of functionality to your component, if this is a little bit too a big of a challenge for you.