7.7: Adding Photo Upload in Angular

Now that we have our photo upload capability on the back-end, let's add the functionality in the Angular application.

Add PhotoEditorComponent

Inside of the members folder in the SPA project, generate a new component called PhotoEditorComponent:

ng g c members/photo-editor --no-spec

Verify that it's added to app.module.ts

This will be a child component of our MemberEditComponent. So, let's add an Input property of an array of Photos to the photo-editor.component.ts file:

export class PhotoEditorComponent implements OnInit {
  @Input() photos: Photo[];

  constructor() { }

  ngOnInit() {
  }

}

PhotoEditorTemplate

Update photo-editor.component.htmls to:

<div class="row">
  <div class="col-md-2" *ngFor="let photo of photos">
    <img class="thumbnail" src="{{ photo.url }}" alt="{{ photo.description }}">
    <div class="row justify-content-center">
      <button type="button" class="btn btn-sm btn-secondary">Main</button>
      <button type="button" class="btn btn-sm btn-warning"><i class="fa fa-trash-o"></i></button>
    </div>
  </div>
</div>

Next, add it to the MemberEditComponent where we have placeholder text of Edit photos will go here.

We'll also grab the photos to send to our PhotoEditorComponent's Input property from our MemberEditComponent's User property:

<tab heading="Edit Photos">
    <app-photo-editor [photos]="user.photos"></app-photo-editor>
</tab>

Add Styling to the Component

Let's add a custom color to our for warnings. In styles.scss add the following:

$orange: #f79569;

//  ...

$theme-colors: (
    "primary": $red,
    "secondary": $cyan,
    "warning": $orange          //   <--- Added
);

And, in photo-editor.component.scss, add the following style:

img.thumbnail {
    height: 100px;
    width: 100px;
    margin-bottom: 3px;
}

Add File Uploader

We're going to use another library to handle file uploading called ng2-file-upload. It's by the same people that wrote our ngx-bootstrap library. See the docs here.

Run the following command to install the library:

npm install ng2-file-upload --save

Import it into the app.module.ts file and add it to the imports array:

import { FileUploadModule } from 'ng2-file-upload';

//  ...

We'll be copying the examples from the documentation and modifying them to our needs.

In photo-editor.component.ts, modify it to this:

export class PhotoEditorComponent implements OnInit {
  @Input() photos: Photo[];
  uploader: FileUploader;
  hasBaseDropZoneOver = false;

  constructor() { }

  ngOnInit() {
  }

  public fileOverBase(e: any): void {
    this.hasBaseDropZoneOver = e;
  }

}

Next, in our photo-editor.template.html template, below the </div> where we left off last time, add the following:

Wiring Up File Uploader

Now, we need to implement an initializeUploader() method. We'll also inject the AuthService and add the base URL from our environment.

export class PhotoEditorComponent implements OnInit {
  @Input() photos: Photo[];
  uploader: FileUploader;
  hasBaseDropZoneOver = false;
  baseUrl = environment.apiUrl;

  constructor(private _authService: AuthService) { }

  ngOnInit() {
    this.initializeUploader();
  }

  public fileOverBase(e: any): void {
    this.hasBaseDropZoneOver = e;
  }

  initializeUploader() {
    this.uploader = new FileUploader({
      url: this.baseUrl + 'users/' + this._authService.decodedToken.nameid + '/photos',
      authToken: 'Bearer ' + localStorage.getItem('token'),
      isHTML5: true,
      allowedFileType: ['image'],
      removeAfterUpload: true,
      autoUpload: false,
      maxFileSize: 10 * 1024 * 1024
    });

    this.uploader.onSuccessItem = (item, response, status, headers) => {
      if (response) {
        const res: Photo = JSON.parse(response);
        const photo = {
          id: res.id,
          url: res.url,
          dateAdded: res.dateAdded,
          description: res.description,
          isMain: res.isMain
        };

        this.photos.push(photo);
      }
    };

  }

}

Test It Out

Now that we have multiple photos, we can also try out our photo carousel:

Last updated