Hello I am using the ionic cordova camera, file and filepath plugin . I am facing this error while selecting and deleting pictures.
When I test it on on separate project, it works. I still can’t find out the problem. could you please guide me?
Error:
ERROR TypeError: Cannot read property 'path' of null
at Object.eval [as updateDirectives] (UploadPhotosPage.html:15)
at Object.debugUpdateDirectives [as updateDirectives] (vendor.js:59830)
at checkAndUpdateView (vendor.js:59226)
at callViewAction (vendor.js:59467)
at execEmbeddedViewsAction (vendor.js:59430)
at checkAndUpdateView (vendor.js:59227)
at callViewAction (vendor.js:59467)
at execComponentViewsAction (vendor.js:59409)
at checkAndUpdateView (vendor.js:59232)
at callViewAction (vendor.js:59467)
polyfills.js:3040 Unhandled Promise rejection: Cannot read property 'destroyed' of null ; Zone: <root> ; Task: Promise.then ; Value: TypeError: Cannot read property 'destroyed' of null
at ViewContainerRef_.push../node_modules/@angular/core/fesm5/core.js.ViewContainerRef_.move (vendor.js:57553)
at vendor.js:3313
at DefaultIterableDiffer.push../node_modules/@angular/core/fesm5/core.js.DefaultIterableDiffer.forEachOperation (vendor.js:55020)
Here is photo_upload.html
<ion-header>
<ion-toolbar>
<ion-title color="primary">Upload Photos</ion-title>
<ion-buttons slot="end">
<ion-button clear (click)="uploadImageData()">Done</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content padding>
<h3 *ngIf="images.length == 0" text-center>Please Select Image!</h3>
<ion-list>
<ion-item *ngFor="let img of images; index as pos" text-wrap>
<ion-thumbnail slot="start">
<ion-img [src]="img.path"></ion-img>
</ion-thumbnail>
<ion-label>
{{ img.name }}
</ion-label>
<ion-button slot="end" fill="clear" (click)="deleteImage(img, pos)">
<ion-icon slot="icon-only" name="trash"></ion-icon>
</ion-button>
</ion-item>
</ion-list>
</ion-content>
<ion-footer>
<ion-toolbar color="primary">
<ion-button fill="clear" expand="full" color="light" (click)="selectImage()">
<ion-icon slot="start" name="camera"></ion-icon>
Select Image
</ion-button>
</ion-toolbar>
</ion-footer>
Here is my photo_uoload.ts file
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { Platform, ActionSheetController, ToastController, LoadingController, AlertController } from '@ionic/angular';
import { Camera, CameraOptions } from '@ionic-native/Camera/ngx';
import { File, FileEntry } from '@ionic-native/File/ngx';
import { Storage } from '@ionic/storage';
import { Router } from '@angular/router';
import { WebView } from '@ionic-native/ionic-webview/ngx';
import { OraclemcsService } from './../../services/oraclemcs.service';
import { presentAlert,UiutilsService } from "../../utils/ui-utility.service";
const STORAGE_KEY = 'care_report_images';
@Component({
selector: 'app-upload-photos',
templateUrl: './upload-photos.page.html',
styleUrls: ['./upload-photos.page.scss'],
})
export class UploadPhotosPage implements OnInit {
constructor(private platform: Platform
, public actionSheetController: ActionSheetController
, private camera: Camera
, private toastController: ToastController
, private file: File
, private storage: Storage
, public router: Router
, private webview: WebView
, private loadingController: LoadingController
, private ref: ChangeDetectorRef
, private alertController: AlertController
, private mcsService: OraclemcsService
) { }
public images = [];
lastImage: string = null;
ngOnInit() {
}
ionViewDidEnter() {
document.addEventListener("backbutton", function (e) {
console.log("disable back button")
}, false);
}
/**
* action selection list
*/
async selectImage() {
if (this.images.length < 3) {
const actionSheet = await this.actionSheetController.create({
header: "Select Image source",
buttons: [{
text: 'Load from Library',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
}
},
{
text: 'Use Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
await actionSheet.present();
}else{ presentAlert("Images limit Exceeded",this.alertController); }
}
/**
* copy picture to file system and update registry
* @param sourceType
*/
public takePicture(sourceType) {
var options: CameraOptions = {
quality: 100,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
this.camera.getPicture(options).then(imagePath => {
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
if (currentName.lastIndexOf('?') > 0)
currentName = currentName.substr(0, currentName.lastIndexOf('?'));
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
});
}
/**
* copy to local directory
*/
copyFileToLocalDir(namePath, currentName, newFileName) {
this.file.copyFile(namePath, currentName, this.file.dataDirectory, newFileName).then(success => {
console.log('in copy file promise');
this.updateStoredImages(newFileName);
console.log(namePath+"1:"+currentName+"2:"+this.file.dataDirectory+"3:"+newFileName);
}, error => {
this.presentToast('Error while storing file.');
});
}
/**
* update registry
* @param name
*/
updateStoredImages(name) {
this.storage.get(STORAGE_KEY).then(images => {
let arr = JSON.parse(images);
if (!arr) {
let newImages = [name];
this.storage.set(STORAGE_KEY, JSON.stringify(newImages));
} else {
arr.push(name);
this.storage.set(STORAGE_KEY, JSON.stringify(arr));
}
let filePath = this.file.dataDirectory + name;
let resPath = this.pathForImage(filePath);
let newEntry = {
name: name,
path: resPath,
filePath: filePath
};
this.images = [newEntry, ...this.images];
console.log(JSON.stringify(this.images));
this.ref.detectChanges(); // trigger change detection cycle
});
}
/**
* alert
* @param text
*/
async presentToast(text) {
const toast = await this.toastController.create({
message: text,
position: 'bottom',
duration: 3000
});
toast.present();
}
/**
* mapped to a url file path
* @param img
*/
pathForImage(img) {
if (img === null) {
return '';
} else {
let converted = this.webview.convertFileSrc(img);
return converted;
}
}
/**
* create file name
*/
createFileName() {
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
return newFileName;
}
/**
* ui remove image
* @param imgEntry
* @param position
*/
deleteImage(imgEntry, position) {
this.images.splice(position, 1);
this.storage.get(STORAGE_KEY).then(images => {
console.log("Delect Img_"+JSON.parse(images));
let arr=JSON.parse(images);
let filtered = arr.filter(name => name != imgEntry.name);
this.storage.set(STORAGE_KEY, JSON.stringify(filtered));
var correctPath = imgEntry.filePath.substr(0, imgEntry.filePath.lastIndexOf('/') + 1);
console.log("Correct Path_"+correctPath +imgEntry.name);
this.file.removeFile(correctPath, imgEntry.name).then(res => {
this.presentToast('File removed.');
this.ref.detectChanges();
});
});
}
async presentAlert(err) {
const alert = await this.alertController.create({
header: 'Alert',
message: err,
buttons: ['OK']
});
await alert.present();
}
}
Here is app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { IonicStorageModule } from '@ionic/storage';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { Camera } from '@ionic-native/Camera/ngx';
import { File } from '@ionic-native/File/ngx';
import { WebView } from '@ionic-native/ionic-webview/ngx';
import { FilePath } from '@ionic-native/file-path/ngx';
import { FileTransfer } from '@ionic-native/file-transfer/ngx';
import { HTTP } from '@ionic-native/http/ngx';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { Network } from '@ionic-native/network/ngx';
import { Toast } from "@ionic-native/toast/ngx";
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
}
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
BrowserModule,
HttpClientModule,
IonicModule.forRoot(),
AppRoutingModule,
IonicStorageModule.forRoot(),
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
providers: [
StatusBar,
SplashScreen,
Camera,
File,
WebView,
FilePath,
FileTransfer,
HTTP,
Network, Toast,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule { }