Reputation: 147
I have an angular 8 program where I want to edit an item upon clicking edit and the value shows up in their respective forms. So for the name value will display in the name text input. Age will display in the age text input, etc. The problem is when I click edit, the image input file doesn't display or hold the image.
Now how do I display this image by default when clicking edit similar to the text files? I know the text inputs use [(ngModel)] = "value"/>
but this doesn't seem to work for input files. Below is my code for the image input file and the corresponding ts file.
HTML
<div class="form-group">
<input formControlName="ProductFile" #file type="file" name="photo" ng2FileSelect [uploader]="uploader" (change)="previewImage(file.files)" />
<div [hidden]="!imgURL">
<img [src]="imgURL || '//:0'" height="200" >
</div>
</div>
edit file.ts
previewImage(files, product) {
if (files.length === 0)
return;
var mimeType = files[0].type;
if (mimeType.match(/image\/*/) == null) {
return alert('Only image files!');
}
var reader = new FileReader();
this.imagePath = files;
reader.readAsDataURL(files[0]);
reader.onload = (_event) => {
//upload percentage
this.uploadPercent = new Observable((observer) => {
Math.round((_event.loaded / _event.total) * 100);
});
this.imgURL = reader.result;
}
}
Upvotes: 2
Views: 1180
Reputation: 831
Now how do I display this image by default when clicking edit similar to the text files? [...] this doesn't seem to work for input files.
I tried to reproduce your issue in a StackBlitz project (see link).
Without modifying your sample code too much, here's how I got the image to display from input file:
From your template, supply a [formGroup]
directive in the root div
HTML element.
<div class="form-group" [formGroup]="form">
...
</div>
In your component class, define the supplied form
form group, which contains the ProductFile
form control.
form = new FormGroup({
ProductFile: new FormControl(''),
});
Hope this helps.
Upvotes: 0
Reputation: 35
Need Clarification
Your previewImage
function is receiving two arguments but you seem to be sending only one.
Do you want to show a default image before the user selects a file? If this is the case, the change()
lifehook will not help. That is only fired after a new file is selected.
Possible solution
You can save a default file in your assets folder, or anywhere in your filesystem really, and pass it as a default value for imageURL:
imageUrl = 'default-path/file.ext'
If you are getting the default file from a server, send it as a member of a dto class, with byte[]
as its datatype. You can then pass in the raw bytes into src:
// model.kt
data class FileDto(content: ByteArray, ext: string)
// controller
@GetMapping(value = ["/file/{fileId}"])
fun getFile(@PathVariable("fileId") fileId: string): FileDto {
return fileService.fetchFile(UUID.fromString(fileId))
}
// file-service.kt
// assuming filePath and ext are columns in your db table
fun fetchFile(fileId: UUID): FileDto {
return try {
db.findById(fileId).let {
FileDto(FileSystemResource(it.filePath).file.readBytes(), it.ext)
}
}
catch (e: FileNotFoundException) { handleExceptions(e) }
catch(e: IOException) { handleExceptions(e) }
}
private fun handleExceptions(e: Exception): Nothing {
e.printStackTrace()
throw e
}
This endpoint will give you everything you need to display the file:
client-side
// model.ts
// note that the byte array will be stringified (serialized)
// since it is coming from a data class
export interface File {ext: string, content: string}
// file-service.ts
fetchFile(uuid: string): Observable<File> {
return this.httpClient.get<File>(this.baseUrl + 'uuid')
}
//app.component.ts
mimeTypes = new Map([
['jpeg', 'image/jpeg'],
['svg', 'image/svg+xml'],
['pdf', 'application/pdf'],
['docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']
])
imageUrl$ = this.fileService.fetchFile(uuid).pipe(
map(it => this.generateFileUri(it.ext, it.content))
)
private generateFileUri(ext: string, content: string) {
const mimeType = MimeTypes.get(ext)
return `data:${mimeType};base64,${content}`
}
//app.component.html
<img [src]="(imgUrl$ | async) || '//:0'" height="200" >
Upvotes: 1