Skip to content

mrsoto/loopback-example-angular-starter

 
 

Repository files navigation

#Overview This example demonstrates how to use LoopBack with AngularJS.

It's a simple "To Do" list application that uses LoopBack on the back end and AngularJS on the front end.

#Prerequisites Before starting, makes sure you've followed Getting Started with LoopBack to install Node and LoopBack.

Install Bower to manage front-end dependencies:

npm install -g bower

In addition, you will need a basic understanding of:

  • Angular
  • Angular Resource
  • AngularUI Router
  • Bootstrap
  • Bower
  • LoopBack models

#Procedure

If you just want to see the example in action, do this:

git clone https://github.com/strongloop/loopback-example-angular-starter
cd loopback-example-angular-starter
npm install
slc run

Otherwise, follow the steps below to create the application from scratch. The example is a typical Todo list web app.

  1. Create the application.

Run slc loopback, and name the app loopback-example-angular-starter.

  1. Configure db.json.

Edit server/datasources.json to look like:

{
  "db": {
    ...
    "file": "db.json"
  }
}

This change will persist model instances to a JSON file. For more information, see the memory connector documentation.

  1. Create the Todo model.

Run slc loopback:model Todo to create the Todo model. Use the memory connector, expose the model via REST, leave the default plural form and add a required String property called "content".

  1. Add a sample model.

Run slc run to start the server, go to localhost:3000/explorer and add a Todo instance with the following data:

{
  "content": "Buy eggs"
}

Verify that model has been inserted by opening db.json (it will be created where you ran slc run). You should see this:

{
  "ids": {
    "User": 1,
    "AccessToken": 1,
    "ACL": 1,
    "RoleMapping": 1,
    "Role": 1,
    "Todo": 2
  },
  "models": {
    "User": {},
    "AccessToken": {},
    "ACL": {},
    "RoleMapping": {},
    "Role": {},
    "Todo": {
      "1": "{\"content\":\"Buy eggs\",\"id\":1}"
    }
  }
}

Notice the "Todo" property contains the model you just created.

  1. Configure the vendor directory.

Create .bowerrc in the project root with the following contents:

{
  "directory": "client/vendor"
}

Bower installs packages in bower_components by default, but we reconfigure this to client/vendor instead to make it easier to import files into index.html.

  1. Install front-end dependencies.

Run the bower install angular angular-resource angular-ui-router bootstrap from the project root.

  1. Create index.html

In the client directory with the following contents:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <h1>Hello, world!</h1>

    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="js/bootstrap.min.js"></script>
  </body>
</html>

This is just the basic Bootstrap getting started template.

  1. Create style.css.

Create a css directory inside the client directory. Inside the newly created directory, create a file named style.css with the following contents:

body {
  padding-top:50px;
}
.glyphicon-remove:hover {
  cursor:pointer;
}
  1. Add bower dependencies to index.html.

Modify index.html to look like:

...
<title>LoopBack Angular starter example</title>
...
<body ng-app="app">
  <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
    <div class="container">
      <div class="navbar-header">
        <a class="navbar-brand" href="#">LoopBack Angular starter example</a>
      </div>
    </div>
  </div>

  <div class="container">
    <div ui-view></div>
  </div>

  <script src="vendor/jquery/dist/jquery.js"></script>
  <script src="vendor/bootstrap/dist/js/bootstrap.js"></script>
  <script src="vendor/angular/angular.js"></script>
  <script src="vendor/angular-resource/angular-resource.js"></script>
  <script src="vendor/angular-ui-router/release/angular-ui-router.js"></script>
</body>

Use the minified versions of Bower dependencies for your production app.

  1. Configure index.html to be the application entry point.

Remove server/boot/root.js and modify server/server.js to look like:

...
// -- Mount static files here--
// All static middleware should be registered at the end, as all requests
// passing the static middleware are hitting the file system
// Example:
var path = require('path');
app.use(loopback.static(path.resolve(__dirname, '../client')));
...
  1. Create app.js and configure application routes.

In the client directory, create another directory named js. Inside the js directory, create a file named app.js with the following contents:

'use strict';

angular
  .module('app', [
    'ui.router'
  ])
  .config(['$stateProvider', '$urlRouterProvider', function($stateProvider,
      $urlRouterProvider) {
    $stateProvider
      .state('todo', {
        url: '',
        templateUrl: 'js/todo/templates/todo.html',
        controller: 'TodoCtrl'
      });
    $urlRouterProvider.otherwise('todo');
  }]);

For more information on application routing, see AngularUI Router documentation.

If you're using jshint, you can add "predef": ["angular"] to .jshintrc to prevent Angular specific warnings.

Then add apps.js as a dependency in index.html:

...
<script src="vendor/angular-ui-router/release/angular-ui-router.js"></script>
<script src="js/app.js"></script>
...
  1. Create todo.html.

In client/js, create a directory named todo. Inside the todo directory, create another directory named templates. In the templates directory, create a file named todo.html with the following contents:

<h1>Todo list</h1>
<hr>
<form name="todoForm" novalidate ng-submit="addTodo()">
  <div class="form-group"
      ng-class="{'has-error': todoForm.content.$invalid
        && todoForm.content.$dirty}">
    <input type="text" class="form-control focus" name="content"
        placeholder="Content" autocomplete="off" required
        ng-model="newTodo.content">
    <span class="has-error control-label" ng-show="
        todoForm.content.$invalid && todoForm.content.$dirty">
      Content is required.
    </span>
  </div>
  <button class="btn btn-default" ng-disabled="todoForm.$invalid">Add</button>
</form>
<hr>
<div class="list-group">
  <a class="list-group-item" ng-repeat="todo in todos">{{todo.content}}&nbsp;
    <i class="glyphicon glyphicon-remove pull-right"
        ng-click="removeTodo(todo)"></i></a>
</div>
  1. Create controllers.js.

In client/js/todo, create controllers.js with the following contents:

'use strict';

angular
  .module('app')
  .controller('TodoCtrl', ['$scope', '$state', 'Todo', function($scope,
      $state, Todo) {
    $scope.todos = [];
    function getTodos() {
      Todo
        .find()
        .$promise
        .then(function(results) {
          $scope.todos = results;
        });
    }
    getTodos();

    $scope.addTodo = function() {
      Todo
        .create($scope.newTodo)
        .$promise
        .then(function(todo) {
          $scope.newTodo = '';
          $scope.todoForm.content.$setPristine();
          $('.focus').focus(); //JQuery hack for refocusing text input
          getTodos();
        });
    };

    $scope.removeTodo = function(item) {
      Todo
        .deleteById(item)
        .$promise
        .then(function() {
          getTodos();
        });
    };
  }]);

If you know a better way to refocus a text input using purely Angular (instead of the JQuery hack above), submit a pull request please. ;)

Then add controllers.js as a dependency in index.html:

...
<script src="js/app.js"></script>
<script src="js/todo/controllers.js"></script>
...
  1. Generate lb-services.js.

Create a new directory named common in client/js. Switch to the common directory and run:

lb-ng ../../../server/server.js lb-services.js

This generates a file named lb-services.js which is an Angular service used to interface with your back-end server. For more information, see the LoopBack AngularJS SDK.

Next, declare lbServices as a dependency in client/js/app.js:

...
angular
  .module('app', [
    'lbServices',
    'ui.router'
  ])
  ...

Then add lb-services.js as a dependency in index.html:

...
<script src="js/common/lb-services.js"></script>
...
  1. Run the application.

From the project root, enter slc run and browse to localhost:3000 to view the application.

#Notes

#More information For more information, see the LoopBack Angular SDK documentation.

About

The basics on how to use AngularJS with LoopBack.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 99.9%
  • CSS 0.1%