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.
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.
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.
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:
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:
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.
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.
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.
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.
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.
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.
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.
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.
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.
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:
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.
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.
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.
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.
Using data in the view
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.
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!
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”