User profile picture

Note: If you skipped ahead to this section, click here to download a zip of the tutorial at this point.

So now we will add an ability to add a user profile image using the device's camera (e.g. phone or laptop).

The first part is to add the Meteor package that provides us this ability:

$ meteor add okland:camera-ui

We will add now a server method for updating the user's profile image, which is just like updating any other string field of the user's profile:

7.2 Add update picture method lib/methods.js
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    Messages.remove({ chatId: chatId });
 
    return Chats.remove({ _id: chatId });
  },
  updatePicture(data) {
    if (!this.userId) {
      throw new Meteor.Error('not-logged-in',
        'Must be logged in to update his picture.');
    }
 
    check(data, String);
 
    return Meteor.users.update(this.userId, { $set: { 'profile.picture': data } });
  }
});

The next step is adding the button for adding/editing the user's profile image, we will add it in the profile state, so update the view first:

7.3 Add update picture button to profile view client/templates/profile.html
4
5
6
7
8
9
10
11
12
13
14
15
  </ion-nav-buttons>
 
  <ion-content class="profile">
    <a class="profile-picture positive" ng-click="profile.updatePicture()">
      <div ng-if="profile.currentUser.profile.picture">
        <img ng-src="{{ profile.currentUser.profile.picture }}" alt="profile picture">
        edit
      </div>
      <div ng-if="!profile.currentUser.profile.picture" class="upload-placehoder">
        Add photo
      </div>
    </a>

And now we will implement the controller methods, which will use Camera-UI API for getting the image from the device, and then we will use that image and run the server method for updating the image:

7.4 Add update picture logic to profile controller client/scripts/controllers/profile.controller.js
1
2
3
4
5
 
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
35
36
37
38
39
40
41
 
47
48
49
50
import { _ } from 'meteor/underscore';
import { MeteorCameraUI } from 'meteor/okland:camera-ui';
import { Controller } from 'angular-ecmascript/module-helpers';
 
export default class ProfileCtrl extends Controller {
...some lines skipped...
    this.name = profile ? profile.name : '';
  }
 
  updatePicture () {
    MeteorCameraUI.getPicture({ width: 60, height: 60 }, (err, data) => {
      if (err) return this.handleError(err);
 
      this.$ionicLoading.show({
        template: 'Updating picture...'
      });
 
      this.callMethod('updatePicture', data, (err) => {
        this.$ionicLoading.hide();
        this.handleError(err);
      });
    });
  }
 
  updateName() {
    if (_.isEmpty(this.name)) return;
 
...some lines skipped...
  }
 
  handleError(err) {
    if (err.error == 'cancel') return;
    this.$log.error('Profile save error ', err);
 
    this.$ionicPopup.alert({
...some lines skipped...
}
 
ProfileCtrl.$name = 'ProfileCtrl';
ProfileCtrl.$inject = ['$state', '$ionicLoading', '$ionicPopup', '$log'];

We will add now some css for better layout of the profile page:

7.5 Update profile stylesheet client/styles/profile.scss
11
12
13
14
15
16
17
18
      display: block;
      max-width: 50px;
      max-height: 50px;
      min-width: 50px;
      min-height: 50px;
      width: 100%;
      height: 100%;
      border-radius: 50%;

Now to ease the access to the profile page, we will add a link in the settings view:

7.6 Add reference to profile from settings view client/templates/settings.html
3
4
5
6
7
8
9
10
11
12
13
    <div class="padding text-center">
      <button ng-click="settings.logout()" class="button button-clear button-assertive">Logout</button>
    </div>
    <ion-list>
      <ion-item href="#/profile" class="item-icon-right">
        Profile
        <i class="icon ion-chevron-right icon-accessory"></i>
      </ion-item>
    </ion-list>
  </ion-content>
</ion-view>