I have a method that deletes files off of my ionic 4 App. I can run a deleteFile() method which deletes individual files. I Am trying to use a forEach Method to run the through the deleting all files. But it fails after the first deletion.
html
<ion-card *ngFor="let data of list let i = index">
<ion-card-content>
<div >
<div *ngFor="let n of loop let n = index">
<div class = "linkButtons">
<ion-button fill="outline" color="blackgreen" (click)=" DeleteAllFiles( )">delete all Photos</ion-button>>
</div>
</div>
</div>
<div>
<ion-list>
<ion-item *ngFor="let doc of documents; index as pos" class="ion-text-wrap">
<ion-icon name="document" slot="start"></ion-icon>
<ion-textarea auto-grow="true" ><small>{{ doc.name }}</small></ion-textarea>
<ion-button slot="end" fill="clear" (click)="deleteFile(doc, pos)">
<ion-icon slot="icon-only" name="trash"></ion-icon>
</ion-button>
</ion-item>
</ion-list>
</div>
</ion-card-content>
</ion-card>
The (click)="deleteFile(doc, pos) works fine.
The (click)=" DeleteAllFiles( ) fails after the first deletion.
ts
DeleteAllFiles( ): void {
this.documents.forEach(
(imgEntry, position ) => this.deleteFile(imgEntry, position ));
}
deleteFile(imgEntry, position) {
this.documents.splice(position, 1);
this.storage.get('app_DOCS').then(documents => {
let arr = JSON.parse(documents);
console.log("arr ", arr );
let filtered = arr.filter(name => name != imgEntry.name);
console.log("filtered", filtered);
this.storage.set('app_DOCS', JSON.stringify(filtered));
let correctPath = imgEntry.filePath.substr(0, imgEntry.filePath.lastIndexOf('/') + 1);
console.log("correctPath", correctPath);
this.file.removeFile(correctPath, imgEntry.name).then(res => {
this.presentToast('File removed.'); // edit later for one toast pop up
});
});
}
console.logs
list of docs
Documents [
{
"name":"UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_icon-144x144.png",
"path":"ionic://localhost/_app_file_/var/mobile/Containers/Data/Application/F8772763-A219-407D-92CD-EF5178F0EA9C/Library/NoCloud/UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_icon-144x144.png",
"filePath":"file:///var/mobile/Containers/Data/Application/F8772763-A219-407D-92CD-EF5178F0EA9C/Library/NoCloud/UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_icon-144x144.png"
},
{
"name":"UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_44198511-How-to-Fix-FAL-Rifle-Brass-Strikes.pdf",
"path":"ionic://localhost/_app_file_/var/mobile/Containers/Data/Application/F8772763-A219-407D-92CD-EF5178F0EA9C/Library/NoCloud/UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_44198511-How-to-Fix-FAL-Rifle-Brass-Strikes.pdf",
"filePath":"file:///var/mobile/Containers/Data/Application/F8772763-A219-407D-92CD-EF5178F0EA9C/Library/NoCloud/UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_44198511-How-to-Fix-FAL-Rifle-Brass-Strikes.pdf"
}
]
arr
UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_icon-144x144.png,
UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_44198511-How-to-Fix-FAL-Rifle-Brass-Strikes.pdf
filtered UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_44198511-How-to-Fix-FAL-Rifle-Brass-Strikes.pdf
correctPath file:///var/mobile/Containers/Data/Application/F8772763-A219-407D-92CD-EF5178F0EA9C/Library/NoCloud/
arr
UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_icon-144x144.png,UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_44198511-How-to-Fix-FAL-Rifle-Brass-Strikes.pdf
filtered UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_icon-144x144.png
correctPath file:///var/mobile/Containers/Data/Application/F8772763-A219-407D-92CD-EF5178F0EA9C/Library/NoCloud/
imgEntry.name UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_icon-144x144.png
imgEntry.name UUID_5deb6fae-4d84-41ac-8157-01f9c68e73c5_answerID_155_originalName_44198511-How-to-Fix-FAL-Rifle-Brass-Strikes.pdf
Working Code
deleteFile(imgEntry, position): Promise<any> {
console.log("deleteFile selected");
let request = this.storage.get(this.STORAGE_KEY_DOC);
console.log("position", position);
request.then(documents => {
let arr = JSON.parse(documents);
this.documents.splice(position);
// let filtered = arr.filter(name => name != imgEntry.name);
let correctPath = imgEntry.filePath.substr(0, imgEntry.filePath.lastIndexOf('/') + 1);
this.file.removeFile(correctPath, imgEntry.name).then(res => {
let resp = JSON.stringify(res);
console.log("resp", resp);
});
let removeDB = this.storage.set(this.STORAGE_KEY_DOC, JSON.stringify(this.documents));
}).then(( )=> {
});
return request;
}
It is "failing" because you are altering the documents
array whilst you are iterating it.
This is essentially what you have:
var arr = [1, 2, 3, 4];
arr.forEach((v, i) => {
arr.splice(i, 1);
})
console.log(arr);
Which boils down to:
var arr = [1, 2, 3, 4];
arr.splice(0, 1);
arr.splice(1, 1);
arr.splice(2, 1);
arr.splice(3, 1);
console.log(arr);
If greater than the length of the array, start will be set to the length of the array. In this case, no element will be deleted but the method will behave as an adding function, adding as many element as item[n*] provided.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
To conclude, there is no point to splicing the array as you go. Have your .then
implementation keep track of the files successfully deleted and then splice those after the .forEach
has completed. You may want to return the promise from your deleteFile
method so that you can Promise.all()
it at the end.
The example below returns a promise from the deleteFile method. The deleteAll method now maps instead of forEach so that we can store all of the priomises, and then once they are done we will be able to just wipe the documents array. Please not that I updated the below without a compiler, so there may be a couple syntax errors.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
DeleteAllFiles( ): void {
var deleteRequests = this.documents.map((imgEntry, position ) => this.deleteFile(imgEntry, position ));
Promise.all(deleteRequests).then(() => {
this.documents = new Arrray();
});
}
deleteFile(imgEntry, position): Promise<any> {
var request = this.storage.get('app_DOCS');
request.then(documents => {
let arr = JSON.parse(documents);
console.log("arr ", arr );
let filtered = arr.filter(name => name != imgEntry.name);
console.log("filtered", filtered);
this.storage.set('app_DOCS', JSON.stringify(filtered));
let correctPath = imgEntry.filePath.substr(0, imgEntry.filePath.lastIndexOf('/') + 1);
console.log("correctPath", correctPath);
this.file.removeFile(correctPath, imgEntry.name).then(res => {
this.presentToast('File removed.'); // edit later for one toast pop up
});
});
return request;
}