angular.module('plunker', ['ui.router'])
.config(['$stateProvider', function ($stateProvider) {
  $stateProvider
    .state('main', {
      abstract: true,
      templateUrl: 'views/main.html',
      controller: 'MainCtrl'
    })
    .state('main.home', {
      url: '',
    })
    .state('main.posts', {
      url: '/posts',
      templateUrl: 'views/posts.html',
      controller: 'PostsCtrl',
      resolve: {
        posts: function(Posts) {
          return Posts.query();
        }
      }
    })
    .state('main.post', {
      url: '/post/:id',
      templateUrl: 'views/post-edit.html',
      controller: 'PostEditCtrl',
      resolve: {
        post: function($stateParams, $state, $timeout, Posts) {
          var post = new Posts({
              id: $stateParams.id
            }),
            promise = post.load();
          promise.catch(function() {
            $timeout(function() {
              $state.go('main.posts');
            }, 1)
          });
          return promise;
        }
      }
    });
}])
.service('Posts', function($q, $timeout) {
  
  var fixtures = [{
    id: 1,
    title: 'Lorem ipsum dolor',
    content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit'
  }, {
    id: 2,
    title: 'sit amet, consectetur',
    content: 'Phasellus facilisis sem sed massa semper, et interdum mi fermentum'
  }, {
    id: 3,
    title: 'adipiscing elit',
    content: 'Curabitur feugiat lacus in aliquet sodales'
  }, {
    id: 4,
    title: '[Error] Cras diam dui',
    error: true
  } ,{
    id: 5,
    title: 'tincidunt quis orci',
    content: 'Curabitur nec purus eget quam hendrerit aliquam facilisis eget neque'
  } ,{
    id: 6,
    title: '[Error] ac, semper condimentum',
    error: true
  } ,{
    id: 7,
    title: 'elit',
    content: 'Phasellus convallis dolor et nisl pellentesque vehicula'
  }];
  
  function Posts(config) {
    angular.extend(this, config);
  }
  Posts.prototype.load = function() {
    var deferred = $q.defer(),
      self = this;
    
    $timeout(function() {
      angular.extend(self, fixtures[+self.id-1])
      if (self.error) {
        deferred.reject('No content');
      } else {
        deferred.resolve(self);
      }
    }, 2000);
    
    return deferred.promise;
  };
  Posts.query = function() {
    var deferred = $q.defer();
    
    $timeout(function() {
      fixtures.forEach(function(p) {
        delete p.loading;
      });
      deferred.resolve(fixtures)
    }, 2000);
    
    return deferred.promise;
  }
  return Posts;
})
.controller('PostsCtrl', function($scope, posts) {
  $scope.posts = posts;
  
  $scope.$on('$stateChangeStart', function(event, toState, toParams) {
    if ('main.post' === toState.name) {
      $scope.posts.some(function(p) {
        if (+toParams.id === +p.id) {
          p.loading = true;
          return true;
        }
      });
    }
  });
  $scope.$on('$stateChangeSuccess', function(event, toState) {
    if ('main.post' === toState.name) {
      $scope.posts.forEach(function(p) {
        delete p.loading;
      });
    }
  });
  $scope.$on('$stateChangeError', function(event, toState) {
    if ('main.post' === toState.name) {
      $scope.posts.forEach(function(p) {
        delete p.loading;
      });
    }
  });
})
.controller('PostEditCtrl', function($scope, post) {
  $scope.post = post;
})
.controller('MainCtrl', function($scope, $location, $timeout) {
  
  $scope.location = $location;
  
  $scope.isViewLoading = true;
  $scope.$on('$stateChangeStart', function() {
    $scope.isViewLoading = true;
  });
  $scope.$on('$stateChangeSuccess', function() {
    $scope.isViewLoading = false;
  });
  $scope.$on('$stateChangeError', function() {
    $scope.isViewLoading = false;
    $scope.loadingError = true;
    $timeout(
      function() {
        $scope.loadingError = false;
      },
      2000
    );
  });
});
<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <link data-require="bootstrap-css@3.1.1" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
    <script data-require="ui-router@*" data-semver="0.2.8" src="http://angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
    <script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script data-require="bootstrap@*" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
    <script src="app.js"></script>
  </head>

  <body>
    <ui-view></ui-view>
  </body>

</html>
.loading-modal {
  bottom: 0;
  background: transparent;
  z-index: 1;
}
.loading-modal,
.alert-error {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  font-weight: bold;
  text-align: center;
  color: green;
}
.alert-error {
  color: red;
}

@-webkit-keyframes spin {
  from {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }

  to {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

.spin {
  -webkit-animation-name: spin;
  -webkit-animation-duration: 1000ms;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-timing-function: linear;
}
<p ng-if="loading" class="loading">Wait for it…</p>
<div ng-if="!loading">
  <table class="table">
    <thead>
      <tr>
        <th style="width: 3em;"></th>
        <th>Titre</th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="post in posts">
        <td>
          <span ng-show="post.loading"
              class="spin glyphicon glyphicon-refresh"></span>
        </td>
        <td>
          <a ui-sref="main.post({id: post.id})">
            {{post.title}}
          </a>
        </td>
      </tr>
    </tbody>
  </table>
</div>
<div class="form-group">
  <label for="post.title">Titre :</label>
  <input ng-model="post.title"
          class="form-control"
          id="post.title">
</div>
<div class="form-group">
  <label for="post.content">Content :</label>
  <textarea ng-model="post.content"
          class="form-control"
          id="post.content"></textarea>
</div>
<nav class="navbar navbar-default" role="navigation">
  <a ui-sref="main.posts" class="container">Display posts list</a>
</nav>
<div ng-show="isViewLoading" class="loading-modal">
Wait for it…
</div>
<div ng-show="loadingError" class="alert-error">
Une erreur est survenue.
</div>
<p>Current URL : {{location.$$url||'/'}}</p>
<ui-view></ui-view>