2

Expected behavior:

Clicking table row should display only the selected image in a div on the right.

Current State:

Clicking each table row displays the selected image without toggling the image being selected. Another error is that clicking the previous table row again creates another copy of the image.

Plunker

http://plnkr.co/edit/26VanqdKqltbD6Bdclg9?p=preview

media-image.component.html

<div id="media-content-container">
    <div id="media-content-wrapper">
        <div id="upload-selected-images">
            <input
                type="file"
                id="files"
                name="files[]"
                (change)="handleFileSelect($event)"
                multiple />
        </div>
        <table class="table" id="list">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Type</th>
                    <th>Size</th>
                </tr>
            </thead>
            <tbody>
                <tr 
                    *ngFor="let image of images, let i = index "
                    (click)="displayImage(files[i])">
                    <td>{{image.fileName}}</td>
                    <td>{{image.fileType}}</td>
                    <td>{{image.fileSize}}</td>
                </tr>
            </tbody>
        </table>
    </div>
    <div id="selected-image">
    </div>
</div>

media-image.component.ts

import { Component, OnInit }                            from '@angular/core';

@Component({
    selector: 'app-media-image',
    templateUrl: './media-image.component.html',
    styleUrls: ['./media-image.component.css']
})
export class MediaImageComponent implements OnInit {
    images:any = [];
    files:FileList;
    ngOnInit(){
    }

    handleFileSelect(evt) {
        this.files = evt.target.files; // FileList object
        console.log("this.files:: ", this.files);
        for (let i = 0, f; f = this.files[i]; i++) {
            if (!f.type.match('image.*')) {
                continue;
            }
            this.images.push({ 
                fileName: encodeURI(f.name),
                fileType: f.type || 'N/A',
                fileSize: `${f.size} bytes`
            });
            console.log("images:: ", this.images);
        }
    }
    displayImage( f ){
        let reader = new FileReader();

        // Closure to capture the file information.
        reader.onload = (function(theFile) {
            return function(e){
                // Render thumbnail.
                let div = document.createElement('div');
                // div.className = 'ad-images';
                // div.style.cssText = 'display:none';
                div.innerHTML = ['<img style="height:80px;" src="', e.target.result,
                '" title="', encodeURI(theFile.name), '"/>'].join('');
                document.getElementById('selected-image').insertBefore(div, null);
            }
        })(f);
        // Read in the image file as a data URL.
        reader.readAsDataURL(f);
    }
}

media-image.component.css

#media-content-container{
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin: 2em 0;
}
absingharora
  • 134
  • 11

2 Answers2

1

You have 2 ways of doing this.

1) with your current code you can clear the inside of the div by deleting the children of the div, or

2) do it the angular way. You would make the src a variable and this would in turn let angular do the updating.

This link will help you get started on 2 Angular 2 change image src attribute.

SDhaliwal
  • 174
  • 6
1

There were several issues in your code . I fixed them in new plnkr. Plnkr: http://plnkr.co/edit/AzVB1NVvlGwbJ15f5TjZ?p=preview

The second bug is due to this code :

this.files = evt.target.files; 

Every time you are uploading a new image you are resetting the files array. I moved it into the for loop to fix this.


Other code changes are :

New fields in component :

  seletedImageUrl: string;
  selectedImageName: string;

Image upload code :

displayImage( i){
  let reader = new FileReader();
  const selectedFile = this.files[i];

  reader.onload = e => {
      this.selectedImageUrl =e.target.result;
      this.selectedImageName = encodeURI(selectedFile.name);      
  };

  reader.readAsDataURL(selectedFile);
}

HTML

  <img *ngIf="selectedImageUrl && selectedImageName" 
     style="height:80px;" 
     [src]="selectedImageUrl" 
     [title]="selectedImageName"/>
Vamshi
  • 9,194
  • 4
  • 38
  • 54
  • Thank you for helping me debug the issue. Without sharing the answer, can you give me a hint on how to get the width and the height of the image on image load? – absingharora Jun 14 '17 at 05:53
  • You can just use `.width` and `.height` . Check this https://stackoverflow.com/questions/8903854/check-image-width-and-height-before-upload-with-javascript – Vamshi Jun 14 '17 at 05:55
  • img.onload makes sense to me but I need to make sure that I add the width and the height to my images array ( images:any = []; ) to display that value in the table. – absingharora Jun 14 '17 at 06:45
  • I think you should `new Image()` and get the dimensions as mentioned here https://stackoverflow.com/questions/7460272/getting-image-dimensions-using-javascript-file-api .I will help you out later if you are stuck let me know. – Vamshi Jun 14 '17 at 06:58
  • Thank you for that link. I was able to retrieve the dimensions and display the data in the table with a minor concern since I display the dimensions after the user clicks on the – absingharora Jun 14 '17 at 08:15
  • Create a new question in https://codereview.stackexchange.com/ for help refactoring your code – Vamshi Jun 14 '17 at 08:21