Creating an AngularJS/MySQL app in 0.649 seconds

In the video tutorial below, I am creating an AngularJS/MySQL TODO application using Hyper IDE. Hyper IDE is a web based IDE, which among other things, allows you to extremely rapidly create an AngularJS application, which automatically binds towards the server, using an HTTP REST based ORM library for MySQL. Since AngularJS apps is just a template in Hyper IDE, the app will be automatically generated, which allows us to use most of the video to rather explain how the app is wired together, instead of typing out boiler plate code. However, the app also serves as a very nice starting ground, to apply your own modifications, and modify it as you see fit. This allows you to literally, create your first AngularJS/MySQL/REST based web app, in less than one second – For later to modify it as you see fit yourself.

Below is a screenshot of how it looks like, if you chose to check out the app in Hyper IDE yourself.

Then you can watch the video below, where I walk through the app, and explain most of its aspects in great details. For the record, if you’d like to reproduce this locally, you’ll have to read what I write at the bottom of this article, since the code I am running in the video, has not yet been released, but can be found in my GutHub repositories.

The two most important files that Hyper IDE will create for us, is our HTML file, and our JavaScript file. I have included these files below, for your convenience. First our HTML file. This is the file that is called “index.html”.

<!doctype html>
<html ng-app='todoApp'>
  <head>
    <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js'></script>
    <script src='modules/todo/controller.js'></script>
    <link rel='stylesheet' type='text/css' href='/modules/micro/media/main.css' />
    <link rel='stylesheet' type='text/css' href='/modules/micro/media/skins/serious.css' />
    <link rel='stylesheet' type='text/css' href='modules/todo/styles.css' />
  </head>
  <body>
    <div class='container'>
      <div class='row'>
        <div class='col'>
          <div ng-controller='TodoListController as todoList' class='shaded air-inner bg rounded'>
            <h1>Todo</h1>
            <form ng-submit='todoList.addTodo()'>
              <div class='new-item strip'>
                <input type='text' autocomplete='off' ng-model='todoList.todoText' placeholder='Add item ...' id='newItem'>
                <input type='submit' class='submit-button' value='add'>
              </div>
            </form>
            <div>
              <ul class='todos'>
                <li ng-repeat='todo in todoList.todos' ng-click='todoList.delete(todo.id)'>{{todo.description}}</li>
              </ul>
            </div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

The important parts above to notice, is how we create an “ng-app” declaration in our body, in addition to the “ng-controller” parts. The instance of our “TodoListController”, created through our “ng-controller” declaration, is later used inside of both our form, which submits a new item. In addition to in our bulleted list, which is an “ng-repeat” (repeater), creating on “li” element, for each item in our “todoList” instance. The controller ties together our view, with our MySQL back end, through Hyper Core, which allows us to query our MySQL database, using HTTP REST requests. Below you can see our JavaScript controller. This is the file that is called “controller.js”

/*
 * Main module for our Angular app.
 */
angular.module ('todoApp', [])

  /*
   * Our only controller, responsible for invoking our server side back end,
   * and databinding our view.
   */
  .controller ('TodoListController', function ($scope, $http) {

    /*
     * Fetching existing items from our server.
     */
    var todoList = this;
    $http.get ('/hyper-core/mysql/todo/items/select?[limit]=50').
      then (function successCallback (response) {
        todoList.todos = response.data;
    });
 
    /*
     * Invoked by our view when a new item has been added by user.
     * Invokes the MySQL server-side back end, and inserts the newly inserted
     * item into our "view".
     */
    todoList.addTodo = function () {

      /*
       * Invoking our server-side method, to insert item into our database.
       *
       * Notice, server-side back end requires a 'PUT' request for our 'insert' method.
       *
       * The URL we use is in the format of '/hyper-core/mysql/[database]/[table]/[operation]'.
       */
      $http ({
        method:'PUT', 
        url: '/hyper-core/mysql/todo/items/insert', 

        /*
         * Our server-side requires the data for our insert operation to be URL encoded,
         * hence we'll need to transform from the default serialization logic of Angular,
         * which is JSON, to URL encoded data.
         */
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        transformRequest: function (obj) {
          var str = [];
          for (var p in obj) {
            str.push (encodeURIComponent (p) + '=' + encodeURIComponent (obj [p]));
          }
          return str.join ('&');
        },
        data: {description: document.getElementById ('newItem').value}
      }).then (function successCallback (response) {

        /*
         * Pushing our new item into our list of items, and making sure
         * we set our textbox' value to empty.
         */
        todoList.todos.push ({
          description: todoList.todoText, 
          id:response.data.id
        });
        todoList.todoText = '';
      });
    };
 
    /*
     * Invoked by our view when an item is deleted.
     */
    todoList.delete = function (id) {

      /*
       * Deleting our clicked item from our list of items from our view.
       */
      for(var idx = 0; idx < todoList.todos.length; idx++) {
        if (todoList.todos [idx].id === id) {
          todoList.todos.splice (idx,1);
          break;
        }
      }

      /*
       * Invoking our server-side method, to delete item from our database.
       *
       * Notice, server-side back end requires a 'DELETE' request.
       */
      $http.delete('/hyper-core/mysql/todo/items/delete?id=' + id);
    }
  });

In our above controller, we basically just have two functions. One which is invoked when an item is inserted, and another which is invoked when an item is deleted. They both use Hyper Core to invoke our server side, which again transforms our requests into SQL queries, and updates our database accordingly. All in all, not too bad for 0.649 seconds of coding 😉

Notice – The code necessary to reproduce this, is not yet released – But you can probably figure out how to fork the relevant GitHub repositories for both Phosphorus Five, Hyper IDE, and Hyper Core if you want to try it out yourself today.

Edit – In the following video, I demonstrate how you can even modify the app, online, on my home server.

Advertisements

An HTTP REST based ORM

JavaScript has suffered from the lack of good tooling for a long time, when seeking to map your client-side code towards server-side logic, and retrieving data. The security issues here too, have historically been a nightmare. To combat this problem, I set out to create an HTTP REST based generic ORM set of services, which allows you to generically do all for basic CRUD operations for MySQL; select, delete, update and insert of course.

It is built such that each separate operation has its own unique URL. This has a lot of benefits, since it’s easy to grant or deny access to some resource, and discriminate access clearance, according to the URL, and the user’s role. But first, let’s talk about our 4 different operations.

Select example

You can easily perform a select type of query, through an HTTP GET request, which again will return some JSON object, containing the results of your query. Pass in criteria for your select as query parameters, and you can decorate it easily. Below is an example.

/database/your-database/your-table/select?[columns]=name,email&[order-by]=name&[limit]=10&[offset]=50

The above will retrieve 10 items from the “your-database” database, and its “your-table” table. It will order the results by the “name” column, and select from the 50th item and out. It will return a JSON array, containing only the “name” and the “email” columns. Since it is very easy to assign access right to a virtual URL such as the above in Phosphorus Five, this allows you to assign access right to users, according to their roles.

In addition to “select” queries, you can also do “insert”, “update” and “delete” – And it will generically work, regardless of your database schema, towards any table, allowing you to apply a whole range of parameters, filtering your end results one way or another. If you want to select only items that are beyond the name of “Hansen” for instance, you can add a where clause, using the >= operator, as a part of your HTTP GET query.

You can find the project here. Notice, it’s currently in ALPHA state …

You can see a video of me demonstrating it below. The project contains some sample code, which you can probably easily modify to serve your own needs.