Tag Archives: JavaScript

Dynamic List Items in an Ionic/AngularJS App

In an Ionic/AngularJS app when one wants to display a list of model objects, the following will typically be used:

<ion-list>
  <ion-item ng-repeat="item in items">
    Hello, {{item}}!
  </ion-item>
</ion-list>

In an app I’m currently working on, however, I wanted to make use of different items in a list dynamically, with the appearance of each item depending on various properties of the given model object in the list. I’d imagine that to solve this problem there are various ways of doing so, but I ended up using html view templates and the ng-include directive to achieve this. Below is a step-by-step walkthrough of the method I used:

  • Define HTML view templates for the different list items to be displayed.

TemplateA.html

{{modelObject.name}}

TemplateB.html

<img class="full-image" ng-src="{{modelObject.image.url}}">
<p>
	{{modelObject.description}}
</p>
  • Add functions in the controller to determine the correct class & view template to use based on properties of the provided model object.

HomeCtrl.js

.controller('HomeCtrl', function($scope) {
  var vm = $scope;

  // Determines the correct CSS class to use based
  // on properties of the provided model object
  vm.itemClass = function(modelObject) {
    if (modelObject.type == 0) {
      return "class-A";
    }
    else {
      return "class-B"
    }
  };

  // Determines the correct html view template to use based
  // on properties of the provided model object
  vm.itemTemplate = function(modelObject) {
    if (modelObject.type == 0) {
      return "app/path_to_template/templateA.html";
    }
    else {
      return "app/path_to_template/templateB.html";
    }
  };
});
  • Then in the view displaying the list, it’s as simple as referencing the relevant controller functions to dynamically determine the correct class and template to use for each item in the list at runtime.

Home.html

    <ion-list>
      <ion-item ng-repeat="modelObject in modelObjects" ng-class="itemClass(modelObject)">
        <ng-include src="itemTemplate(modelObject)"></ng-include>
      </ion-item>
    </ion-list>
Advertisements

Uploading a base64 image to Parse with the REST API in AngularJS

Screen Shot 2015-05-31 at 8.34.44 PM

I was recently working on an Ionic/AngularJS app which needed to do the following:

– Upload a base64 image file (taken with the camera) to the Parse servers using the REST API.

– Associate the uploaded image file with an object and save the object to Parse using the REST API.

 

The Parse documentation didn’t seem to explain this specific case and other examples online seemed to all offer different details on how to get this done… so I ended up jumping through a few hoops until I eventually got it working. Below is an example of what I used to achieve this.

ImageSubmissionCtrl

// camera is simply an injected service, wrapping the cordova APIs
.controller('ImageSubmissionCtrl', function($scope, $http, camera) {

  var vm = $scope;
  var imageData;

  // Object to save to Parse that includes an image
  var object = {
    text: "",
    image: null
  };

  // Function to take a picture using the device camera
  vm.takePicture = function() {

    // Define various properties for getting an image using the camera
    var cameraOptions = {
      quality : 75,
      // This ensures the actual base64 data is returned, and not the file URI
      destinationType: Camera.DestinationType.DATA_URL,
      encodingType : Camera.EncodingType.JPEG
    };

    // Use the Cordova Camera APIs to get a picture. For brevity, camera
    // is simply an injected service
    camera.getPicture(cameraOptions).then(function(returnedImageData) {
      imageData = returnedImageData;

    }, function(err) {
      console.log("Error taking picture: " + err);
    });
  };

  // Function to submit the object to Parse using the REST API
  vm.submitObject = function() {

    // This part is important. As part of the JSON that we send to Parse,
    // we need to specify the content type here as a field(__ContentType)
    // along with the image data. Notice that the Content-Type specified
    // in the headers is actually "plain/text"
    var dataToSubmit = {__ContentType : "image/jpeg", base64 : imageData};

    // First upload the image file
    $http.post("https://api.parse.com/1/files/image.jpg", dataToSubmit, {
           headers: {
               "X-Parse-Application-Id": PARSE_APP_ID,
               "X-Parse-REST-API-Key": PARSE_REST_API_KEY,
               "Content-Type": "plain/text"
           }
    })
    .success(function(result) {
      // Now associated the image file with the object
      coupleImageFileWithObject(result.name);
    })
    .error(function(result) {
      console.log("Error uploading image file: " + err);
    });
  };

  // Function to associate the image file with an object and save the
  // object to Parse using the REST API
  function coupleImageFileWithObject(fileName) {

    // Assign the filename to our object prior to saving it to Parse
    object.image = {name : fileName, __type : "File"};

    // The 'ObjectClass' in the url should be replaced by the class name
    // of the object you are saving
    $http.post("https://api.parse.com/1/classes/ObjectClass", object, {
           headers: {
               "X-Parse-Application-Id": PARSE_APP_ID,
               "X-Parse-REST-API-Key": PARSE_REST_API_KEY
             }
      })
      .success(function(result) {
        console.log("Object successfully saved.");
      })
      .error(function(result) {
        console.log("Error coupling image file with object: " + err);
      });
  };
});

It’s important to understand that the first step is to upload the file to Parse independently of the containing object, and then only on a successful response associate the file handle with the object and save the object itself to Parse.