Austin Knight UI/UX Designer & Software Engineer

Easy Javascript Object TypeError Protection

If you are writing javascript, it’s safe to say you are working with objects on a regular basis (not to mention the fact that objects are a huge part of how javascript works, and javascript’s primitives like arrays, string, booleans, etc. get wrapped in objects when you call specific methods on them). Usually when I’m working with an object, it’s because I am handling data of some kind, like a local state object or a JSON object returned from an API call. When accessing objects, properties may be one, two, three or more levels deep in the structure. Here is an example object we’ll use for reference:

const user = {
  id: 1,
  name: 'Rod Kimble',
  username: 'Hotrod',
  email: 'rodk@email.com',
  address: {
    street: 'Kulas Light',
    suite: 'Apt. 556',
    city: 'Gwenborough',
    zipcode: '92998-3874',
    geo: {
      lat: '-37.3159',
      lng: '81.1496'
    }
  },
  phone: '1-770-736-8031 x56442',
  website: 'hildegard.org',
  company: {
    name: 'Romaguera-Crona',
    catchPhrase: 'Multi-layered client-server neural-net',
    bs: 'harness real-time e-markets'
  }
}

To access any property of this user object, you could simply do things like:

console.log(user.id)
// => 1

console.log(user.address)
// => {
        street: 'Kulas Light',
        suite: 'Apt. 556',
        city: 'Gwenborough',
        zipcode: '92998-3874',
        geo: {
          lat: '-37.3159',
          lng": '81.1496'
        }
      }

console.log(user.company.name)
// => 'Romaguera-Crona'

What happens when you try to access a property on the object that doesn’t exist?

console.log(user.birthdate)
// => undefined

Nothing too terrible right? If the property doesn’t exist on the object, undefined will be returned as the value. Now what happens if you try to access a property two, three, or more levels deep, where both levels don’t exist?

console.log(user.birthdate.month)
// => Uncaught TypeError: Cannot read property 'month' of undefined

Bad things happen, horrible things, things you don’t want to see! The severity of what happens varies greatly depending on the context of where the attempt to access the property is happening. This type of error can be pretty bad because it often leads to infinite loops, frozen apps, bad data, or just silent failures that lead to who knows what down the line. There are some things we can do though to protect ourselves against nasty bugs like this. You may find it redundant or an unnecessary to add an extra step, but you’re really going to save yourself some time and headache in the long run by being proactive about accessing object properties safely. A tried and true method for accessing nested object properties safely is to simply check for the existence of a property before trying to do anything with it. For example, you could use a simple if statement:

// Our default date
let bday = {};

if(user.birthday) {
  // do some stuff with user.birthday because we know it's got a value if we get into the if block.
  bday = user.birthday  
}

if(user.birthday && user.birthday.month) {
  // We get into this block if the user has a birthday, AND, if the user's birthday has a month property with a value.
  bday.month = user.birthday.month
}

Great, now we’re accessing properties in a safe way. Using this method is perfectly fine, but as you can see it can quickly get out of hand when you add more and more checks. The if statements will continue to grow and you’re going to spend an unnecessary amount of time parsing through the block trying to figure things out. A more developer-friendly method I have become accustomed to is to use some handy tools created by the folks maintaining Lodash. Aside from some convenient utility functions for accessing object properties, there is a whole host of other useful functionality Lodash provides for working with various javascript data structures. I’ll leave you to explore what else Lodash has to offer, but for the purposes of this article, we’re going to look specifically at the get method. Let’s look at the user birthday example again using this approach:

import _ from 'lodash';

let bday = {};

// Same as `user.birthday`
bday = _.get(user, 'birthday', {});

// Same as `user.birthday.month`
bday.month = _.get(user, 'birthday.month');

First, we’re importing Lodash from NPM. We can access the different methods of Lodash by using the_ character. In the get method, the first argument is the object you want to access, the second argument is a string of the path you want to access, and the third argument is a default value to return. The default value you set in the third argument will be returned if Lodash is unsuccessful in finding a value at the path you’ve given. If you do not set a default value like the last line in our example, that is ok too because get will return undefined for you by default. For more examples, see the documentation at https://lodash.com/docs/4.17.4#get. As a general rule of thumb, I will use Lodash get when I need to access a property in an object that is more than one level deep. It can be useful to use get when searching the first level if you want to return a default value that is something other than undefined though.

That’s it for this bit on object properties. Let me know what you think or if you have any questions in the comments.

React - Import External Libraries With Webpack

I’ve been writing a lot more with React these days, and along with React I’ve learned some new build tools that are commonly accepted among the React community, namely Webpack. If you are familiar with Webpack, you know it’s pretty simple to include a list of javascript files you want bundled. When using import or require statements to include module dependencies in components, Webpack goes out and includes those files in the bundle. It looks a little something like this when writing a React component:

  import React from 'react';
  import Twilio from 'twilio'

  const myComponent = () => {
    const handleClick = () => {
      Twilio.Device.setup();
    }

    return(
      <div>
        <button onClick={handleClick}>Click It</button>
      </div>
    )
  }

I’m not going to go into how to set up webpack (you can read the docs here), but based on how you’ve configured your build, webpack will know that it needs to include the Twilio module in the final bundle because we’ve explicitly imported it in this file. However, I ran into a tricky problem using a javascript client library from Twilio. The library is typical of most javascript client libraries in that it wants to add itself to the global window context of your application. A lot of modules I use in components are simply objects and functions that operate independent of window, but sometimes I need a client library of another application and those typically use window. Unfortunately, modules that depend on the global window context don’t play nice with the Webpack bundler, because webpack won’t execute scripts in the global context by default. One solution to this problem could be to load this dependency that relies on window by using one script tag to load window dependent modules and another script tag to load the bundled js file that includes the rest of the application, but that extracts code out of the managed bundle and the window dependent modules may not be accessible when you expect it them be in your components. To get around this, webpack has a handy little loader, conveniently called the “script loader”. It allows us to require a script in a component, like any other module dependency, but it tells webpack to execute the file in the global context once, and will not parse the require statement for that file. This basically behaves the same as loading the file in a script tag, but it gives the guarantee of being accessible within the module that needs it.</p>

In order to use the script loader, it will need to be installed via NPM. Once installed, you should be able to require the module that depends on window using the script loader syntax. The syntax is a simple require statement with script! prepended to the file path of the script. Webpack will pick up this syntax and handle loading the file appropriately.

  import React from 'react';
  require('script!../path/to/your/script/twilio-client.js');

  const myComponent = () => {
  const handleClick = () => {
    Twilio.Device.setup();
  }

  return(
    <div>
      <button onClick={handleClick}>Click It</button>
    </div>
  )

Now that the script is loading through the script loader, we can just access the module like any other standard global method. It’s not necessary to assign the require statement to a named variable because the script loader will just execute the script, which will place the module’s methods onto the global window context as expected.

Ionic Framework - Import Phone Contacts

I have been working with the Ionic Framework the past couple of months building a hybrid web/native app. There are a few cool things that I have been able to do, like sending push notifications, text messages, and getting access to phone contacts through my app. This post in particular will give you an example of how to gain access to the iOS phone contacts, where you can extract pretty much any information you have available for a contact. I’ll assume you already know how to get up and running with the Ionic framework; If you are not familiar with Ionic, they have a pretty good getting started guide that can walk you through the process of setting up an app at http://ionicframework.com/getting-started/.

Setting Up Dependencies

Ionic is built on top of Cordova with AngularJS. This will allow us to use an awesome suite of plugins via the angular module ngCordova. Let’s start by including the ngCordova module in our app. Go to http://ionicframework.com/getting-started/ and download ngCordova. This will download the whole plugin suite. We could create a custom build, but for simplicity sake we will take the whole enchilada! Place the ng-cordova.min.js file wherever you would like and add the file to your app’s index.html after your angular and ionic scripts, but before the cordova.js script. You can also install the module files via a package manager like bower or NPM, ionic comes packaged with both. We will also change the title of the header bar to be more accurate as to what we are looking at.

  <!DOCTYPE html>
  <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
      <title></title>

      <link href="lib/ionic/css/ionic.css" rel="stylesheet">
      <link href="css/style.css" rel="stylesheet">
      <!-- ionic/angularjs js -->
      <script src="lib/ionic/js/ionic.bundle.js"></script>

      <!-- Angular ngCordova -->
      <script src="lib/ngCordova/dist/ng-cordova.min.js"></script>

      <!-- cordova script (this will be a 404 during development) -->
      <script src="cordova.js"></script>

      <!-- your app's js -->
      <script src="js/app.js"></script>
    </head>
    <body ng-app="contactsApp">

      <ion-pane>
        <ion-header-bar class="bar-stable">
          <h1 class="title">Contact App</h1>
        </ion-header-bar>
        <ion-content>
        </ion-content>
      </ion-pane>
    </body>
  </html>

For this demo, we will call our app ‘contactsApp’. After you have included the required ngCordova file, we need to add it to our main contactsApp module as a dependency. Simply inject ‘ngCordova’ into your app’s dependency list like so:

  angular.module('contactsApp', ['ionic', 'ngCordova'])

  .run(function($ionicPlatform) {
    $ionicPlatform.ready(function() {
      // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
      // for form inputs)
      if(window.cordova && window.cordova.plugins.Keyboard) {
        cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      }
      if(window.StatusBar) {
        StatusBar.styleDefault();
      }
    });
  });

Now our app will have access to any of the ngCordova plugins available. The final step to be able to use the contacts plugin is to add the specific plugin to our Cordova project. Ionic creates specific platform build files, and these build files need access to native plugins. We get access to native functions via ngCordava which calls up Cordova plugins and their functions. To be able to use the contact contacts module that is provided by ngCordova, we need to install the Cordova contacts plugin for our iOS build. To do so, go into the base directory of your project in your terminal and enter the following command to install:

  cordova plugin add org.apache.cordova.contacts

Next, go into the /plugins directory and location the folder org.apache.cordova.contacts. We will need to copy the contents of /src/ios to the build of our iOS project. Hopefully you already understand how to build your app, if not the getting started tutorial I linked above will be able to walk you through the build process. After you have copied the plugin files, locate the /platforms/ios directory. This is the native build of your app where we need to copy the plugin files to. Inside the /ios folder, locate the folder /contacts-app and then go into the /Plugins directory. Inside this directory we need to create a new folder named exactly the same as the original plugin folder org.apache.cordova.contacts. Once you have created this folder, copy the contents from before into it. You should have a CDVContact.h and CDVContact.h, CDVContact.m, CDVContacts.h, and CDVContacts.m files inside this folder now. Placing the files in the build’s plugin directory gives the app the access it needs to the Cordova plugins.

Using The Module

Now let’s create a controller that will utilize the $cordovaContacts module to call up our phone’s contact list. For this demo, I’ll just add the controller in the same file as the main app. In a real application you would probably have your controllers, services, etc. living in different places as their own modules. We are going to name our controller contactsCtrl and we will require $scope and $cordovaContacts as dependencies. The code within the .run function comes pre-packed with an ionic application; it basically checks to see if the app is running yet and initializes a couple of ionic functions for us. You can also inject $ionicPlatform anywhere else you need to check if the app has loaded yet.

  angular.module('contactsApp', ['ionic', 'ngCordova'])

  .run(function($ionicPlatform) {
    $ionicPlatform.ready(function() {
      // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
      // for form inputs)
      if(window.cordova && window.cordova.plugins.Keyboard) {
        cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      }
      if(window.StatusBar) {
        StatusBar.styleDefault();
      }
    });
  })

  .controller('contactsCtrl', function($scope, $cordovaContacts){});

The code within the .run function come pre-packed with an ionic application; it basically checks to see if the app is running yet and initializes a couple of ionic functions for us. You can also inject $ionicPlatform anywhere else you need to check if the app has loaded yet.

Now that we have a controller available, we can add it to our markup in the index.html file. In a larger app, you would probably have some sort of $state controller that handles setting up views and templates. In this demo we will just keep it simple and add some more markup inside the ion-content area. Our contactsCtrl will just go on the ion-content tag, and we will fill in the rest of what we need for showing our contents inside of this tag.

  <ion-content ng-controller="contactsCtrl"></ion-content>

Back in our controller, we will utilize the $cordovaContacts module to ask for the phone’s contact list. We will add the $scope variable getContacts, which will contain a function that we can bind to a button in the view. Inside the function, we will add another $scope variable called phoneContacts, which will be an empty array that we’ll push the contacts into once we get them. Since the variable is set every time the function is called, it will clear out any data we may already have and replace it with a new set.

  controller('contactsCtrl', function($scope, $cordovaContacts){
    $scope.getContacts = function() {
      $scope.phoneContacts = [];
    };
  });

We can add our function to the view by using the ngClick directive on a button, in which we will initialize our $scope variable getContacts. We’ll wrap this up in a div with an ionic class ‘padding’ so there is some space around the container. Adding another ionic class ‘button’ will make our button a little better than the default iOS styling.

  <ion-content ng-controller="contactsCtrl">
    <div class="padding">
      <button class="button" ng-click="getContacts()">Get My Contacts</button>
    </div>
  </ion-content>

The last thing to add in our controller is the call to $cordovaContacts, and it’s success or failure callbacks. I’ve separated out the success and failure callbacks into named private functions for easier readability. If the call to get contacts fails, onError gets called. If the call succeeds, onSuccess gets called and completes adding contact information to our phoneContacts $scope variable. Notice that when we call $cordovaContacts, we pass in some options. In this case, we only tell the module that we want multiple contacts returned, meaning all of them. If you did not specify this, you would only get one contact in return. The module is actually pretty flexible, in that you can pass in options to only return one specific property of a contact if you don’t want all the data. In this case though, we will take it all! You can check out more about options in the Cordova documentation.

  controller('contactsCtrl', function($scope, $cordovaContacts){
    $scope.getContacts = function() {
      $scope.phoneContacts = [];

      function onSuccess(contacts) {
        for (var i = 0; i < contacts.length; i++) {
          var contact = contacts[i];
          $scope.phoneContacts.push(contact);
        }
      };

      function onError(contactError) {
        alert(contactError);
      };

      var options = {};
      options.multiple = true;

      $cordovaContacts.find(options).then(onSuccess, onError);
    };
  });

If we built our project in it’s current state and ran it, all would work as expected, and we would actually get contacts. Awesome! But, they won’t actually show up in the view because we haven’t bound our phoneContacts $scope variable to the view anywhere. We’ll use some default ionic layouts for displaying the contacts as some nice looking cards that will show us a contact’s name, phone numbers, and email addresses. We also have access to a whole host of other information, but I will leave that for you to explore or ask questions about.

  <ion-content ng-controller="contactsCtrl">
    <div class="padding">
      <button class="button" ng-click="getContacts()">Get My Contacts</button>
      <div class="list" ng-show="phoneContacts">
        <div class="card" ng-repeat="contact in phoneContacts">
          <div class="item item-divider">
            
          </div>
          <div class="item item-text-wrap">
            <p><strong>Phone(s)</strong></p>
            <div ng-repeat="number in contact.phoneNumbers">
              <p></p>
            </div>
            <p><strong>Email(s)</strong></p>
            <div ng-repeat="email in contact.emails">
              <p></p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </ion-content>

Running the Final Product!

That should do it for getting contacts, all that is left is to build the project by running <code class="in-text-code">ionic build ios</code> and then emulate the project on the iOS simulator by running <code class="in-text-code">ionic emulate ios</code>. You can also open up the file contacts-app.xcodeproj in platforms/ios in Xcode if you want to switch up device types for fun. Running this app on a web server won’t really work though because the web won’t have any contacts to look up.

If you would like to clone a working copy of this demo, check out the repo at https://github.com/austinknight/ionic-import-contacts-demo. There are a few instructions on how to make it run.

Making a Weather App with AngularJS and $HTTP Requests

AngularJS has some awesome stuff out of the box that allows for making data requests to an API a breeze. With the $http module, we can make an Asynchronous Javascript and XML (aka AJAX) request in only a few lines of code. If you haven’t used Angular yet, making requests with $http is similar to the jQuery $.ajax() method used for requests. We give some configurations and receive a promise in return; mostly the same thing in Angular.

For this example, I’ll assume that you already know how to get your application bootstrapped with AngularJS and have a basic understanding of things like $scope, binding data, services/factories, and controllers. If not, you can read up here https://docs.angularjs.org/tutorial/. I’ll include getting the app set up since this is my first Angular post though. You can see the demo at the bottom of the post.

As an example, we’re going to build miniature application that will allow us to look up the weather anywhere in the United States. We’ll use a factory to fetch our data from an api, then we’ll add a controller to set our data to the $scope so we can use it. We will then make practical use of our data to search for weather by zip code.

Setting up the app

First, let’s bootstrap our app with Angular. Include the angular script within the head tag and add a new file in your js directory called app.js, this is where we will invoke our app. This also uses the angular served js file, which shouldn’t be used in a production environment.

  <!DOCTYPE html>
  <html>
    <head>
      <meta charset="utf-8" />
      <title>AngularJS Plunker</title>
      <script>document.write('<base href="' + document.location + '" />');</script>
      <link rel="stylesheet" href="style.css" />
      <script data-require="angular.js@1.2.x" src="https://code.angularjs.org/1.2.16/angular.js" data-semver="1.2.16"></script>
      <script src="app.js"></script>
    </head>
    <body>
    </body>
  </html>

Inside of the app.js file, start by adding a new variable called app and set it to the angular module method with the first argument being the name of the application, which I am calling ‘weatherApp’, and the second to an empty array. The empty array is where dependencies that your app may rely on get injected. More on this to come in our data factory.

  angular.module('weatherApp', []);

Now that we have our app set, include the app.js file in your html, it can go after the angular.js script. Then we will attach our app to the document by adding the ng-app attribute to the html tag, setting it equal to the name of the app we just created - like this:

  <html ng-app="weatherApp">

Getting the data

Now we have a functioning angular application. On to the good stuff, let’s set up a factory to fetch the data we need to find the weather. Back in the app.js file, we can use our app variable to call our application to add a new factory using the .factory() method. Adding a new factory is similar to how we created our app, the first argument is the name we want to give the factory and the second argument is an array of our dependency modules given as strings. This will be a little different however because we will add a function as our last dependency. This is what gets executed whenever our factory is called up and injects the dependencies. The function also takes in the same sibling dependencies that the function resides in. You can read up more about the reason for this structure here, and has mostly to do with minification issues https://docs.angularjs.org/tutorial/step_05#-prefix-naming-convention. Finally, the factory will return an object with keys that we can use in our controller to call the function we’ll make.

  app.factory('weatherService', ['$http', '$q', function ($http, $q){
    return {

    };
  }]);

With our factory created, we can add some functionality to it. We will only need one function to make our GET request to the api, and it will be called getWeather which is returned in our object for use wherever we decide to inject weatherService. In the code above, you can see $http and $q were passed in as dependencies. We can use Angular’s built in $http service to make our get request and $q to create the promise we return. Below is the full function used to make a request to our api for some data. We will either get a success or an error, either one returning some sort of promise with data or an error.

  app.factory('weatherService', ['$http', '$q', function ($http, $q){
    function getWeather (zip) {
      var deferred = $q.defer();
      $http.get('https://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20FROM%20weather.forecast%20WHERE%20location%3D%22' + zip + '%22&format=json&diagnostics=true&callback=')
        .success(function(data){
          deferred.resolve(data.query.results.channel);
        })
        .error(function(err){
          console.log('Error retrieving markets');
          deferred.reject(err);
        });
      return deferred.promise;
    }

    return {
      getWeather: getWeather
    };
  }]);

Let’s break this down a bit. The getWeather function takes in a zip code that get passed to the url we send in our request. The first line in the function sets our $q dependency equal to a more readable name that we will use inside our api call. Next, we make our call to the api via the get method on the $http service. Since this is a public api, we only need to specify the url to the data we want. No matter what the outcome, the $http request will always return a promise. If we get some data returned from the server, we will enter the success function which resolves our promise with the data requested; otherwise we will get some sort of error messaging and the promise will get rejected. That’s it for this service, we can now use this to get some data through our controller that we will be able to set on the scope for interacting with by the user.

####Passing data along Setting up a controller is similar to setting up a factory. We will instead used the .controller() method on our app variable. In the controller we’ll need the $scope and the weatherService module we just made to inject as dependencies. Our first line in the controller will make a call to the weatherService’s getWeather function that will be invoked when a private function in our controller is called. This does not have to be wrapped in a private function, but we will do so because we want to use this action in multiple places within the controller and we don’t want to repeat ourselves. Since we expect to get a promise back after calling getWeather(), we will chain the .then() method to it and pass in the data that is returned. Once our call is done and the promise has resolved or rejected, we bind the data to the $scope giving it the name ‘place’. The weatherService function should be called as soon as the controller is loaded onto the page, so we can call our private function on the next line using fetchWeather(). We will initially make a call to the api for my zip code, 84105, in Salt Lake City. You can put in whatever numbers you want for displaying a default when the page is loaded, otherwise there will be no data. If you don’t want any data initially, just leave the argument blank.

  app.controller('weatherCtrl', ['$scope', 'weatherService', function($scope, weatherService) {
    function fetchWeather(zip) {
      weatherService.getWeather(zip).then(function(data){
        $scope.place = data;
      });
    }

    fetchWeather('84105');
  }]);

After the above code is in place, we will add a new $scope variable called findWeather and set it equal to a function that takes the zip code as an argument. We can use findWeather() now to attach the functionality to the submit button of the form we will make to look up an area; more to come on this next. This new function on the $scope will essentially do everything the other function does, except it will first clear out any date set for $scope.place so that we don’t have a bunch of data that doesn’t relate to the zip code we are giving. We will use our private function again to call up our new weather location, but clear out the $scope date first.

  app.controller('weatherCtrl', ['$scope', 'weatherService', function($scope, weatherService) {
    function fetchWeather(zip) {
      weatherService.getWeather(zip).then(function(data){
        $scope.place = data;
      });
    }

    fetchWeather('84105');

    $scope.findWeather = function(zip) {
      $scope.place = '';
      fetchWeather(zip);
    };
  }]);

Using data in the view

This should be all the javascript we need to get the data we want to display to the user. We can now bind information in the html using Angular’s binding syntax. Back in the index.html file, we’ll need to attach our controller to the section of the code we want to be able to bind data in. Attaching the controller is similar to attaching the app to the document, instead we will use the ng-controller attribute and set it equal to the name of our controller weatherCtrl. We can place this on the body tag and our controller will be able to set data on any child element. Generally, you want to bind the controller to more specific areas so it cannot be used everywhere, but since this is a demo we’ll make it easy and bind to the body.

  <body ng-controller="weatherCtrl">
  <!--Need some weather stuff-->
  </body>

To see the data that gets returned from our api call, we can use the Angular binding syntax and call up our $scope.place variable with `` and insert it within the body tag. You should see a bunch of json data. We can use anything in that set to display to the user, awesome! In our app we want a user to be able to enter a specific zip code they are interested in. We’ll need to create a form with a number input that gets submitted to our api call address. To get the number from the input, we can use the ng-model attribute and set it equal to any variable name, I am calling it zip. We will now have a variable on the $scope called zip that will have the value of whatever we type into the field. On our submit button, we can attach the findWeather() function we made in our controller by using the ng-click attribute and setting it equal to our function with zip being our argument. Remember, zip is the information we get from our input. Whenever we click submit, our findWeather() function will now be called with whatever we have entered and the data we receive will be set on the $scope variable place. We can now use place with whatever keys that are available in our json data object. You can look at the additional markup I’ve added to get an idea of how you can work with stuff. I’ve added a title for the location, the current weather, and the forecast for the next few days.

  <body ng-controller="weatherCtrl">
    <form>
      <input type="number" ng-model="zip">
      <input type="submit" value="Search" ng-click="findWeather(zip)">
    </form>
    <p ng-show="zip">Searching the forecasts for: </p>
    <div>
      <h1>Forecast For: </h1>
      <h2>Current:  | &deg; <img src="http://l.yimg.com/a/i/us/we/52/.gif"/></h2>
      <div ng-repeat="forecast in place.item.forecast">
        <p><strong></strong></p>
        <p>H: &deg; | L: &deg;</p>
      </div>
    </div>
  </body>

That’s all for this little app. You can play around with the data bindings and arrange the markup however you like to display different information. If you have any questions leave a comment and I’ll try to help you out. Check out the demo below to see it in action!

Demo

Do Your Own Thing

There’s just not enough time in one day. I have too much to do right now. My professor might not give a good grade for that. I’ll do that when I get a real job. They probably think I’m unqualified. What if nobody likes it? Somebody already did that, why should I do it? I don’t know how.

These are just a few of the many phrases that plague me every day as a student. Sometimes they interfere with my creative process, and other times they come up in every day situations. There are things I want to do, or projects I am supposed to create, and I get paralyzed by fear. This is especially prevalent when it comes to doing something outside of my knowledge or skill set. Heck, writing this new blog of mine is beyond my comfort zone and writing capabilities, but I’ve committed to doing it anyways. So what is my point in all of this?

Instead of listening to those things that will hold you back, or those things that you think you could fail at, you just have to do your own thing.

That’s right, do your own thing. I thought of this recently while sitting at my desk in senior studio class. Actually, I thought of this a couple years ago when I was working on a class project that I was finding no enjoyment in. I realized that I wasn’t getting the most out of my education because I had not decided to take real ownership of what I wanted to do. I know I am not the first tell you to do your own thing, but my perspective on this idea is probably different than others. We all have opinions right? Let me share mine with you.

I have come to notice about halfway through college that too many people, especially students, get caught up in doing things for that sake of someone else. Whether it is doing a project a certain way to please your professor for that good grade, being a bit conservative on an idea because it might be too risky, or deciding not to try something because you don’t know how. I have gone down that road many times, and it has always led me to a less satisfying outcome. When I finally decided to do my own thing, rather than trying to please a professor or impress my peers, it opened up a huge door I kept passing by. I realized that learning wasn’t just something you do for twenty-some years of your life, but rather something you do for your whole life. I decided to take advantage of this idea and enjoy learning on my own terms; I decided to do my own thing. There is just something great about learning and accomplishing, or even failing at, something you’ve decided to do that is challenging, difficult and risky.

Learning to design and code for websites has probably been one of the biggest challenges I have ever faced. I chose to pursue a degree in graphic design, and through that journey I fell in love with web design somewhere along the way. The program I am in doesn’t necessarily teach how to design for the web, let alone how to actually code a website. There are no web based assignments I was given, and no requirements to learn it. I took the initiative to learn web design/development on my own time, and adapt what I learned into the projects I was tasked to do in school. I by no means have it all figured out yet, and I still have a long road ahead of me before I can really call myself a professional. But what matters most is that I have realized that I will be learning things my whole life, and that web design is what I am naturally better at and have the drive to learn more about than anything else. This my own thing that I have chosen to do.

If you want to get the most out of your formal educational experience, and life in general for that matter, learn how to do your own thing within the limitations that are given to you. This even goes for informal education after you graduate. Andy Rutledge, in his book “Design Professionalism,” sums this up pretty well:

“The most important lesson an inspiring design professional can learn is to take responsibility for his or her own education. Your education I up to you. Your teachers and professors can’t “learn” you anything. You have to learn it, internalize it, and make it your won so that you apply your understanding intuitively in practice. What’s more, it is not your teachers’ job to prepare you for life or to give you the entire syllabus for what is required. Their job is to point the way toward the path you should follow. Period.”

If we don’t learn to do our own thing, and only live through the experience of others, we will become illiterate. Your education can get in a rut somewhere along the way, but it is important to realize that you will be learning for your whole life. If you want to be a designer, you have to continue learning or you will fail. You will be left behind in this fast-paced environment we work in. I was watching a talk by August de los Reyes on “The Myth of Design Education”, and the end of his talk he left the audience with a quote to ponder on the topic of educating yourselves. It was helpful for me in putting this idea of doing your own thing into perspective, so I will leave it with you to ponder as well.

“The illiterate of the future will not be the person who cannot read. It will be the person who does not know how to learn” -AlvinToffler

References in this article:

© 2017 Austin Knight