diff --git a/springboot-petclinic-client/bower.json b/springboot-petclinic-client/bower.json
index 145f7d8bb4405c1b9dfc67bdeefcc7f0b06dce3b..89f91536a78732e7c2992682933a82ee9898aa37 100644
--- a/springboot-petclinic-client/bower.json
+++ b/springboot-petclinic-client/bower.json
@@ -18,8 +18,8 @@
   ],
   "dependencies": {
     "angular": "~1.5.8",
-    "angular-route": "~1.5.8",
     "bootstrap": "components/bootstrap#~3.3.7",
-    "jquery": "components/jquery#~3.1.0"
+    "jquery": "components/jquery#~3.1.0",
+    "angular-ui-router": "ui-router#^0.3.2"
   }
 }
diff --git a/springboot-petclinic-client/src/scripts/app.js b/springboot-petclinic-client/src/scripts/app.js
index 7af1a5e0b383d790d63b6051fb74298847efe9bb..870aeb2097b022111f9ce63d7c2095142c089ec3 100644
--- a/springboot-petclinic-client/src/scripts/app.js
+++ b/springboot-petclinic-client/src/scripts/app.js
@@ -1,37 +1,29 @@
 'use strict';
 /* App Module */
 var petClinicApp = angular.module('petClinicApp', [
-    'ngRoute', 'layoutNav', 'layoutFooter', 'layoutWelcome',
+    'ui.router', 'layoutNav', 'layoutFooter', 'layoutWelcome',
     'ownerList', 'ownerDetails', 'ownerForm', 'petForm', 'visits', 'vetList']);
 
-petClinicApp.config(['$locationProvider', '$routeProvider', '$httpProvider', function(
-    $locationProvider, $routeProvider, $httpProvider) {
+petClinicApp.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', '$httpProvider', function(
+    $stateProvider, $urlRouterProvider, $locationProvider, $httpProvider) {
 
     // safari turns to be lazy sending the Cache-Control header
     $httpProvider.defaults.headers.common["Cache-Control"] = 'no-cache';
 
     $locationProvider.hashPrefix('!');
 
-    $routeProvider.when('/welcome', {
-        template: '<layout-welcome></layout-welcome>'
-    }).when('/owners/:ownerId', {
-        template: '<owner-details></owner-details>'
-    }).when('/owners', {
-        template: '<owner-list></owner-list>'
-    }).when('/owners/:ownerId/edit', {
-        template: '<owner-form></owner-form>'
-    }).when('/new-owner', {
-        template: '<owner-form></owner-form>'
-    }).when('/owners/:ownerId/new-pet', {
-        template: '<pet-form></pet-form>'
-    }).when('/owners/:ownerId/pets/:petId', {
-        template: '<pet-form></pet-form>'
-    }).when('/owners/:ownerId/pets/:petId/visits', {
-        template: '<visits></visits>'
-    }).when('/vets', {
-        template: '<vet-list></vet-list>'
-    }).otherwise('/welcome');
-
+    $urlRouterProvider.otherwise('/welcome');
+    $stateProvider
+        .state('app', {
+            abstract: true,
+            url: '',
+            template: '<ui-view></ui-view>'
+        })
+        .state('welcome', {
+            parent: 'app',
+            url: '/welcome',
+            template: '<layout-welcome></layout-welcome>'
+        });
 }]);
 
 ['welcome', 'nav', 'footer'].forEach(function(c) {
diff --git a/springboot-petclinic-client/src/scripts/fragments/nav.html b/springboot-petclinic-client/src/scripts/fragments/nav.html
index fab8edf7848d882b33c37d87defb0e2feb6c6e65..8d3ac092535afc8ea2365067c5f881a3bc8ed875 100644
--- a/springboot-petclinic-client/src/scripts/fragments/nav.html
+++ b/springboot-petclinic-client/src/scripts/fragments/nav.html
@@ -11,11 +11,9 @@
         <div class="navbar-collapse collapse" id="main-navbar">
             <ul class="nav navbar-nav navbar-right">
                 <li class="active">
-                    <a href="#!/welcome"
-                       title="home page">
+                    <a ui-sref="welcome" title="home page">
                         <span class="glyphicon glyphicon-home" aria-hidden="true"></span>
                         <span>Home</span>
-
                     </a>
                 </li>
 
@@ -24,20 +22,17 @@
                        aria-haspopup="true" aria-expanded="false">Owners<span class="caret"></span>
                     </a>
                     <ul class="dropdown-menu">
-                        <li><a href="#!/owners"><span class="glyphicon glyphicon-search" aria-hidden="true"></span><span> All</span></a></li>
-                        <li><a href="#!/new-owner"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span><span> Register</span></a></li>
+                        <li><a ui-sref="owners"><span class="glyphicon glyphicon-search" aria-hidden="true"></span><span> All</span></a></li>
+                        <li><a ui-sref="ownerNew"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span><span> Register</span></a></li>
                     </ul>
                 </li>
 
                 <li class="">
-                    <a href="#!/vets"
-                       title="veterinarians">
-
+                    <a ui-sref="vets" title="veterinarians">
                         <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
                         <span>Veterinarians</span>
-
                     </a>
                 </li>
             </ul>
         </div>
-</nav>
\ No newline at end of file
+</nav>
diff --git a/springboot-petclinic-client/src/scripts/owner-details/owner-details.component.js b/springboot-petclinic-client/src/scripts/owner-details/owner-details.component.js
index cbf9492eb80901f0b4c1caac431f415533848105..3569642df2e2a0f8fcf55eea47ec624ae9957a60 100644
--- a/springboot-petclinic-client/src/scripts/owner-details/owner-details.component.js
+++ b/springboot-petclinic-client/src/scripts/owner-details/owner-details.component.js
@@ -1,16 +1,7 @@
 'use strict';
 
-angular.module('ownerDetails', [
-    'ngRoute'
-]);
-
-angular.module("ownerDetails").component("ownerDetails", {
-    templateUrl: "scripts/owner-details/owner-details.template.html",
-    controller: ["$http", '$routeParams', function($http, $routeParams) {
-        var self = this;
-
-        $http.get('owner/' + $routeParams.ownerId).then(function(resp) {
-            self.owner = resp.data;
-        });
-    }]
-});
\ No newline at end of file
+angular.module('ownerDetails')
+    .component('ownerDetails', {
+        templateUrl: 'scripts/owner-details/owner-details.template.html',
+        controller: 'OwnerDetailsController'
+    });
\ No newline at end of file
diff --git a/springboot-petclinic-client/src/scripts/owner-details/owner-details.controller.js b/springboot-petclinic-client/src/scripts/owner-details/owner-details.controller.js
new file mode 100644
index 0000000000000000000000000000000000000000..f66274c0157f74d95940a0a0b5fc6e5a1c821c19
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/owner-details/owner-details.controller.js
@@ -0,0 +1,10 @@
+'use strict';
+
+angular.module('ownerDetails')
+    .controller('OwnerDetailsController', ['$http', '$stateParams', function ($http, $stateParams) {
+        var self = this;
+
+        $http.get('owner/' + $stateParams.ownerId).then(function (resp) {
+            self.owner = resp.data;
+        });
+    }]);
diff --git a/springboot-petclinic-client/src/scripts/owner-details/owner-details.js b/springboot-petclinic-client/src/scripts/owner-details/owner-details.js
new file mode 100644
index 0000000000000000000000000000000000000000..670f24beebd460b816e2ca243fe63dc8bd274291
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/owner-details/owner-details.js
@@ -0,0 +1,11 @@
+'use strict';
+
+angular.module('ownerDetails', ['ui.router'])
+    .config(['$stateProvider', function ($stateProvider) {
+        $stateProvider
+            .state('ownerDetails', {
+                parent: 'app',
+                url: '/owners/details/:ownerId',
+                template: '<owner-details></owner-details>'
+            })
+    }]);
\ No newline at end of file
diff --git a/springboot-petclinic-client/src/scripts/owner-details/owner-details.template.html b/springboot-petclinic-client/src/scripts/owner-details/owner-details.template.html
index 5450aa0ea2fd5257580ef02d762e90d00bcf1fd2..ed2810f9caef70346a734b3d560ad9da0713d59f 100644
--- a/springboot-petclinic-client/src/scripts/owner-details/owner-details.template.html
+++ b/springboot-petclinic-client/src/scripts/owner-details/owner-details.template.html
@@ -19,10 +19,10 @@
     </tr>
     <tr>
         <td>
-            <a class="btn btn-default" href="#!/owners/{{$ctrl.owner.id}}/edit">Edit Owner</a>
+            <a class="btn btn-default" ui-sref="ownerEdit({ownerId: $ctrl.owner.id})">Edit Owner</a>
         </td>
         <td>
-            <a href="#!/owners/{{$ctrl.owner.id}}/new-pet" class="btn btn-default">Add New Pet</a>
+            <a ui-sref="petNew({ownerId: $ctrl.owner.id})" class="btn btn-default">Add New Pet</a>
         </td>
     </tr>
 </table>
@@ -30,11 +30,11 @@
 <h2>Pets and Visits</h2>
 
 <table class="table table-striped">
-    <tr ng-repeat="pet in $ctrl.owner.pets">
+    <tr ng-repeat="pet in $ctrl.owner.pets track by pet.id">
         <td valign="top">
             <dl class="dl-horizontal">
                 <dt>Name</dt>
-                <dd><a href="#!/owners/{{$ctrl.owner.id}}/pets/{{pet.id}}">{{pet.name}}</a></dd>
+                <dd><a ui-sref="petEdit({ownerId: $ctrl.owner.id, petId: pet.id})">{{pet.name}}</a></dd>
                 <dt>Birth Date</dt>
                 <dd>{{pet.birthDate | date:'yyyy MMM dd'}}</dd>
                 <dt>Type</dt>
@@ -49,21 +49,20 @@
                     <th>Description</th>
                 </tr>
                 </thead>
-                <tr ng-repeat="visit in pet.visits">
+                <tr ng-repeat="visit in pet.visits track by visit.id">
                     <td>{{visit.date | date:'yyyy MMM dd'}}</td>
                     <td>{{visit.description}}</td>
                 </tr>
                 <tr>
                     <td>
-                        <a href="#!/owners/{{$ctrl.owner.id}}/pets/{{pet.id}}">Edit Pet</a>
+                        <a ui-sref="petEdit({ownerId: $ctrl.owner.id, petId: pet.id})">Edit Pet</a>
                     </td>
                     <td>
-                        <a href="#!/owners/{{$ctrl.owner.id}}/pets/{{pet.id}}/visits">Add Visit</a>
+                        <a ui-sref="visits({ownerId: $ctrl.owner.id, petId: pet.id})">Add Visit</a>
                     </td>
                 </tr>
             </table>
         </td>
-
     </tr>
 </table>
 
diff --git a/springboot-petclinic-client/src/scripts/owner-form/owner-form.component.js b/springboot-petclinic-client/src/scripts/owner-form/owner-form.component.js
index 2f832ef68b93bc81626d888cdefec58a3b0f3eaf..dd409691b5ba0beb9bbf98d246b3b6c3694ad487 100644
--- a/springboot-petclinic-client/src/scripts/owner-form/owner-form.component.js
+++ b/springboot-petclinic-client/src/scripts/owner-form/owner-form.component.js
@@ -1,41 +1,7 @@
 'use strict';
 
-angular.module('ownerForm', [
-    'ngRoute'
-]);
-
-angular.module("ownerForm").component("ownerForm", {
-    templateUrl: "scripts/owner-form/owner-form.template.html",
-    controller: ["$http", '$routeParams', '$location', function ($http, $routeParams, $location) {
-        var self = this;
-
-        var ownerId = $routeParams.ownerId || 0;
-
-        if (!ownerId) {
-            self.owner = {};
-        } else {
-            $http.get("owner/" + ownerId).then(function(resp) {
-                self.owner = resp.data;
-            });
-        }
-
-        self.submitOwnerForm = function() {
-            var id = self.owner.id;
-            var req;
-            if (id) {
-                req = $http.put("owner/" + id, self.owner);
-            } else {
-                req = $http.post("owner", self.owner);
-            }
-
-            req.then(function () {
-                $location.url("/owners");
-            }, function (response) {
-                var error = response.data;
-                alert(error.error + "\r\n" + error.errors.map(function (e) {
-                        return e.field + ": " + e.defaultMessage;
-                    }).join("\r\n"));
-            });
-        };
-    }]
-});
\ No newline at end of file
+angular.module('ownerForm')
+    .component('ownerForm', {
+        templateUrl: 'scripts/owner-form/owner-form.template.html',
+        controller: 'OwnerFormController'
+    });
\ No newline at end of file
diff --git a/springboot-petclinic-client/src/scripts/owner-form/owner-form.controller.js b/springboot-petclinic-client/src/scripts/owner-form/owner-form.controller.js
new file mode 100644
index 0000000000000000000000000000000000000000..55bbe96298966cfd8328f9bae839e6a4501d9102
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/owner-form/owner-form.controller.js
@@ -0,0 +1,35 @@
+'use strict';
+
+angular.module('ownerForm')
+    .controller('OwnerFormController', ["$http", '$state', '$stateParams', function ($http, $state, $stateParams) {
+        var self = this;
+
+        var ownerId = $stateParams.ownerId || 0;
+
+        if (!ownerId) {
+            self.owner = {};
+        } else {
+            $http.get("owner/" + ownerId).then(function (resp) {
+                self.owner = resp.data;
+            });
+        }
+
+        self.submitOwnerForm = function () {
+            var id = self.owner.id;
+            var req;
+            if (id) {
+                req = $http.put("owner/" + id, self.owner);
+            } else {
+                req = $http.post("owner", self.owner);
+            }
+
+            req.then(function () {
+                $state.go('owners');
+            }, function (response) {
+                var error = response.data;
+                alert(error.error + "\r\n" + error.errors.map(function (e) {
+                        return e.field + ": " + e.defaultMessage;
+                    }).join("\r\n"));
+            });
+        };
+    }]);
diff --git a/springboot-petclinic-client/src/scripts/owner-form/owner-form.js b/springboot-petclinic-client/src/scripts/owner-form/owner-form.js
new file mode 100644
index 0000000000000000000000000000000000000000..1bb61591346cd1b223d3ddb0b53b0ad7f930d29b
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/owner-form/owner-form.js
@@ -0,0 +1,16 @@
+'use strict';
+
+angular.module('ownerForm', ['ui.router'])
+    .config(['$stateProvider', function ($stateProvider) {
+        $stateProvider
+            .state('ownerNew', {
+                parent: 'app',
+                url: '/owners/new',
+                template: '<owner-form></owner-form>'
+            })
+            .state('ownerEdit', {
+                parent: 'app',
+                url: '/owners/:ownerId/edit',
+                template: '<owner-form></owner-form>'
+            })
+    }]);
diff --git a/springboot-petclinic-client/src/scripts/owner-list/owner-list.component.js b/springboot-petclinic-client/src/scripts/owner-list/owner-list.component.js
index bba44cd2419f42a683adb03c1e89d2ac8a253797..55b6b253f53030b5802e3269e54dd96b8e535108 100644
--- a/springboot-petclinic-client/src/scripts/owner-list/owner-list.component.js
+++ b/springboot-petclinic-client/src/scripts/owner-list/owner-list.component.js
@@ -1,15 +1,7 @@
 'use strict';
 
-angular.module('ownerList', [
-    'ngRoute'
-]);
-
-angular.module("ownerList").component("ownerList", {
-    templateUrl: "scripts/owner-list/owner-list.template.html",
-    controller: ["$http", function ($http) {
-        var self = this;
-        $http.get('owner/list').then(function(resp) {
-            self.owners = resp.data;
-        });
-    }]
-});
\ No newline at end of file
+angular.module('ownerList')
+    .component('ownerList', {
+        templateUrl: 'scripts/owner-list/owner-list.template.html',
+        controller: 'OwnerListController'
+    });
diff --git a/springboot-petclinic-client/src/scripts/owner-list/owner-list.controller.js b/springboot-petclinic-client/src/scripts/owner-list/owner-list.controller.js
new file mode 100644
index 0000000000000000000000000000000000000000..991c6c644005b98ca919e39b9090b4fc1178b97b
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/owner-list/owner-list.controller.js
@@ -0,0 +1,10 @@
+'use strict';
+
+angular.module('ownerList')
+    .controller('OwnerListController', ['$http', function ($http) {
+        var self = this;
+
+        $http.get('owner/list').then(function (resp) {
+            self.owners = resp.data;
+        });
+    }]);
diff --git a/springboot-petclinic-client/src/scripts/owner-list/owner-list.js b/springboot-petclinic-client/src/scripts/owner-list/owner-list.js
new file mode 100644
index 0000000000000000000000000000000000000000..4714a2f97930edfd9088a60d5695597fcee63d22
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/owner-list/owner-list.js
@@ -0,0 +1,11 @@
+'use strict';
+
+angular.module('ownerList', ['ui.router'])
+    .config(['$stateProvider', function ($stateProvider) {
+        $stateProvider
+            .state('owners', {
+                parent: 'app',
+                url: '/owners',
+                template: '<owner-list></owner-list>'
+            })
+    }]);
\ No newline at end of file
diff --git a/springboot-petclinic-client/src/scripts/owner-list/owner-list.template.html b/springboot-petclinic-client/src/scripts/owner-list/owner-list.template.html
index 37603db6acd92035b54555e54f3051617a59e65f..fc784631a7d088e3094ccee990c524beac371bb6 100644
--- a/springboot-petclinic-client/src/scripts/owner-list/owner-list.template.html
+++ b/springboot-petclinic-client/src/scripts/owner-list/owner-list.template.html
@@ -17,15 +17,15 @@
     </tr>
     </thead>
 
-    <tr ng-repeat="owner in $ctrl.owners | filter:$ctrl.query">
+    <tr ng-repeat="owner in $ctrl.owners | filter:$ctrl.query track by owner.id">
         <td>
-            <a href="#!/owners/{{owner.id}}">
+            <a ui-sref="ownerDetails({ ownerId: owner.id })">
                 {{owner.firstName}} {{owner.lastName}}
             </a>
         </td>
         <td class="hidden-sm hidden-xs">{{owner.address}}</td>
         <td>{{owner.city}}</td>
         <td>{{owner.telephone}}</td>
-        <td class="hidden-xs"><span ng-repeat="pet in owner.pets">{{pet.name + ' '}}</span></td>
+        <td class="hidden-xs"><span ng-repeat="pet in owner.pets track by pet.id">{{pet.name + ' '}}</span></td>
     </tr>
-</table>
\ No newline at end of file
+</table>
diff --git a/springboot-petclinic-client/src/scripts/pet-form/pet-form.component.js b/springboot-petclinic-client/src/scripts/pet-form/pet-form.component.js
index 187356659ba3c4939dfbca35eebc9e85c27f7515..6f5e13bb6e0d91dbbdfb3d96b724b4aa401ce428 100644
--- a/springboot-petclinic-client/src/scripts/pet-form/pet-form.component.js
+++ b/springboot-petclinic-client/src/scripts/pet-form/pet-form.component.js
@@ -1,66 +1,7 @@
 'use strict';
 
-angular.module('petForm', [
-    'ngRoute'
-]);
-
-angular.module("petForm").component("petForm", {
-    templateUrl: "scripts/pet-form/pet-form.template.html",
-    controller: ["$http", '$routeParams', '$location', function ($http, $routeParams, $location) {
-        var self = this;
-        var ownerId = $routeParams.ownerId || 0;
-
-        $http.get('petTypes').then(function(resp) {
-            self.types = resp.data;
-        }).then(function () {
-
-            var petId = $routeParams.petId || 0;
-
-            if (petId) { // edit
-                $http.get("owner/" + ownerId + "/pet/" + petId).then(function(resp) {
-                    self.pet = resp.data;
-                    self.pet.birthDate = new Date(self.pet.birthDate);
-                    self.petTypeId = "" + self.pet.type.id;
-                });
-            } else {
-                $http.get('owner/' + ownerId).then(function(resp) {
-                    self.pet = {
-                        owner: resp.data.firstName + " " + resp.data.lastName
-                    };
-                    self.petTypeId = "1";
-                })
-
-            }
-        });
-
-        self.submit = function() {
-            console.log(this.pet);
-
-            var id = self.pet.id || 0;
-
-            var data = {
-                id : id,
-                name : self.pet.name,
-                birthDate : self.pet.birthDate,
-                typeId: self.petTypeId
-            };
-
-            var req;
-            if (id) {
-                req = $http.put("owners/" + ownerId + "/pets/" + id, data);
-            } else {
-                req = $http.post("owners/" + ownerId + "/pets", data);
-            }
-
-            req.then(function () {
-                $location.url("owners/" + ownerId);
-            }, function (response) {
-                var error = response.data;
-                error.errors = error.errors || [];
-                alert(error.error + "\r\n" + error.errors.map(function (e) {
-                        return e.field + ": " + e.defaultMessage;
-                    }).join("\r\n"));
-            });
-        };
-    }]
-});
\ No newline at end of file
+angular.module('petForm')
+    .component('petForm', {
+        templateUrl: 'scripts/pet-form/pet-form.template.html',
+        controller: 'PetFormController'
+    });
diff --git a/springboot-petclinic-client/src/scripts/pet-form/pet-form.controller.js b/springboot-petclinic-client/src/scripts/pet-form/pet-form.controller.js
new file mode 100644
index 0000000000000000000000000000000000000000..fd4c005d4299fbc71c60bc87016215fede1b5de7
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/pet-form/pet-form.controller.js
@@ -0,0 +1,58 @@
+'use strict';
+
+angular.module('petForm')
+    .controller('PetFormController', ['$http', '$state', '$stateParams', function ($http, $state, $stateParams) {
+        var self = this;
+        var ownerId = $stateParams.ownerId || 0;
+
+        $http.get('petTypes').then(function (resp) {
+            self.types = resp.data;
+        }).then(function () {
+
+            var petId = $stateParams.petId || 0;
+
+            if (petId) { // edit
+                $http.get("owner/" + ownerId + "/pet/" + petId).then(function (resp) {
+                    self.pet = resp.data;
+                    self.pet.birthDate = new Date(self.pet.birthDate);
+                    self.petTypeId = "" + self.pet.type.id;
+                });
+            } else {
+                $http.get('owner/' + ownerId).then(function (resp) {
+                    self.pet = {
+                        owner: resp.data.firstName + " " + resp.data.lastName
+                    };
+                    self.petTypeId = "1";
+                })
+
+            }
+        });
+
+        self.submit = function () {
+            var id = self.pet.id || 0;
+
+            var data = {
+                id: id,
+                name: self.pet.name,
+                birthDate: self.pet.birthDate,
+                typeId: self.petTypeId
+            };
+
+            var req;
+            if (id) {
+                req = $http.put("owners/" + ownerId + "/pets/" + id, data);
+            } else {
+                req = $http.post("owners/" + ownerId + "/pets", data);
+            }
+
+            req.then(function () {
+                $state.go("owners", {ownerId: ownerId});
+            }, function (response) {
+                var error = response.data;
+                error.errors = error.errors || [];
+                alert(error.error + "\r\n" + error.errors.map(function (e) {
+                        return e.field + ": " + e.defaultMessage;
+                    }).join("\r\n"));
+            });
+        };
+    }]);
diff --git a/springboot-petclinic-client/src/scripts/pet-form/pet-form.js b/springboot-petclinic-client/src/scripts/pet-form/pet-form.js
new file mode 100644
index 0000000000000000000000000000000000000000..70292ad68ba542b6843a1c039c1c72ad781dff09
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/pet-form/pet-form.js
@@ -0,0 +1,16 @@
+'use strict';
+
+angular.module('petForm', ['ui.router'])
+    .config(['$stateProvider', function ($stateProvider) {
+        $stateProvider
+            .state('petNew', {
+                parent: 'app',
+                url: '/owners/:ownerId/new-pet',
+                template: '<pet-form></pet-form>'
+            })
+            .state('petEdit', {
+                parent: 'app',
+                url: '/owners/:ownerId/pets/:petId',
+                template: '<pet-form></pet-form>'
+            })
+    }]);
diff --git a/springboot-petclinic-client/src/scripts/pet-form/pet-form.template.html b/springboot-petclinic-client/src/scripts/pet-form/pet-form.template.html
index 36884378c0f65edc149bd9a9821c3534f0cadc41..76317e5575c55b34ceb23356d74b526391db5963 100644
--- a/springboot-petclinic-client/src/scripts/pet-form/pet-form.template.html
+++ b/springboot-petclinic-client/src/scripts/pet-form/pet-form.template.html
@@ -28,7 +28,7 @@
         <label class="col-sm-2 control-label">Type</label>
         <div class="col-sm-6">
             <select class="form-control" ng-model="$ctrl.petTypeId">
-                <option ng-repeat="t in $ctrl.types" value="{{t.id}}">{{t.name}}</option>
+                <option ng-repeat="t in $ctrl.types track by t.id" value="{{t.id}}">{{t.name}}</option>
             </select>
         </div>
     </div>
diff --git a/springboot-petclinic-client/src/scripts/vet-list/vet-list.component.js b/springboot-petclinic-client/src/scripts/vet-list/vet-list.component.js
index fbe63f46f2ebb5d04892f8c0340713f6d591d08b..892f4f98626e409a018b61d4761e8bb8f623d1f4 100644
--- a/springboot-petclinic-client/src/scripts/vet-list/vet-list.component.js
+++ b/springboot-petclinic-client/src/scripts/vet-list/vet-list.component.js
@@ -1,16 +1,7 @@
 'use strict';
 
-angular.module('vetList', [
-    'ngRoute'
-]);
-
-angular.module("vetList").component("vetList", {
-    templateUrl: "scripts/vet-list/vet-list.template.html",
-    controller: ["$http", '$routeParams', function($http) {
-        var self = this;
-
-        $http.get('vets').then(function(resp) {
-            self.vetList = resp.data;
-        });
-    }]
-});
\ No newline at end of file
+angular.module('vetList')
+    .component('vetList', {
+        templateUrl: 'scripts/vet-list/vet-list.template.html',
+        controller: 'VetListController'
+    });
\ No newline at end of file
diff --git a/springboot-petclinic-client/src/scripts/vet-list/vet-list.controller.js b/springboot-petclinic-client/src/scripts/vet-list/vet-list.controller.js
new file mode 100644
index 0000000000000000000000000000000000000000..3e90bca6ef40d154204675cc33cad55eed2f820a
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/vet-list/vet-list.controller.js
@@ -0,0 +1,10 @@
+'use strict';
+
+angular.module('vetList')
+    .controller('VetListController', ['$http', function ($http) {
+        var self = this;
+
+        $http.get('vets').then(function (resp) {
+            self.vetList = resp.data;
+        });
+    }]);
diff --git a/springboot-petclinic-client/src/scripts/vet-list/vet-list.js b/springboot-petclinic-client/src/scripts/vet-list/vet-list.js
new file mode 100644
index 0000000000000000000000000000000000000000..bcecacc0c8e4a355bc079971ccc6b474af472ce8
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/vet-list/vet-list.js
@@ -0,0 +1,11 @@
+'use strict';
+
+angular.module('vetList', ['ui.router'])
+    .config(['$stateProvider', function ($stateProvider) {
+        $stateProvider
+            .state('vets', {
+                parent: 'app',
+                url: '/vets',
+                template: '<vet-list></vet-list>'
+            })
+    }]);
\ No newline at end of file
diff --git a/springboot-petclinic-client/src/scripts/visits/visits.component.js b/springboot-petclinic-client/src/scripts/visits/visits.component.js
index e083fa1fb70cd71304bf2d5d30c4b93b435e2f41..bf6a17a48cc1a8190359ce505474767434784af9 100644
--- a/springboot-petclinic-client/src/scripts/visits/visits.component.js
+++ b/springboot-petclinic-client/src/scripts/visits/visits.component.js
@@ -1,37 +1,7 @@
 'use strict';
 
-angular.module('visits', [
-    'ngRoute'
-]);
-
-angular.module("visits").component("visits", {
-    templateUrl: "scripts/visits/visits.template.html",
-    controller: ["$http", '$routeParams', '$location', '$filter', function ($http, $routeParams, $location, $filter) {
-        var self = this;
-        var petId = $routeParams.petId || 0;
-        var url = "owners/" + ($routeParams.ownerId || 0) + "/pets/" + petId + "/visits";
-        self.date = new Date();
-        self.desc = "";
-
-        $http.get(url).then(function(resp) {
-            self.visits = resp.data;
-        });
-
-        self.submit = function() {
-
-            var data = {
-                date : $filter('date')(self.date, "yyyy-MM-dd"),
-                description : self.desc
-            };
-            console.log(data);
-            $http.post(url, data).then(function() {
-                $location.url("owners/" + $routeParams.ownerId);
-            }, function (response) {
-                var error = response.data;
-                alert(error.error + "\r\n" + error.errors.map(function (e) {
-                        return e.field + ": " + e.defaultMessage;
-                    }).join("\r\n"));
-            });
-        };
-    }]
-});
\ No newline at end of file
+angular.module('visits')
+    .component('visits', {
+        templateUrl: 'scripts/visits/visits.template.html',
+        controller: 'VisitsController'
+    });
\ No newline at end of file
diff --git a/springboot-petclinic-client/src/scripts/visits/visits.controller.js b/springboot-petclinic-client/src/scripts/visits/visits.controller.js
new file mode 100644
index 0000000000000000000000000000000000000000..607836b4ff89de31e01d5344b53eef6654f85526
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/visits/visits.controller.js
@@ -0,0 +1,30 @@
+'use strict';
+
+angular.module('visits')
+    .controller('VisitsController', ['$http', '$state', '$stateParams', '$filter', function ($http, $state, $stateParams, $filter) {
+        var self = this;
+        var petId = $stateParams.petId || 0;
+        var url = "owners/" + ($stateParams.ownerId || 0) + "/pets/" + petId + "/visits";
+        self.date = new Date();
+        self.desc = "";
+
+        $http.get(url).then(function (resp) {
+            self.visits = resp.data;
+        });
+
+        self.submit = function () {
+            var data = {
+                date: $filter('date')(self.date, "yyyy-MM-dd"),
+                description: self.desc
+            };
+
+            $http.post(url, data).then(function () {
+                $state.go("owners", { ownerId: $stateParams.ownerId });
+            }, function (response) {
+                var error = response.data;
+                alert(error.error + "\r\n" + error.errors.map(function (e) {
+                        return e.field + ": " + e.defaultMessage;
+                    }).join("\r\n"));
+            });
+        };
+    }]);
diff --git a/springboot-petclinic-client/src/scripts/visits/visits.js b/springboot-petclinic-client/src/scripts/visits/visits.js
new file mode 100644
index 0000000000000000000000000000000000000000..10821acaa95508bcebbec486535b7c3893520d87
--- /dev/null
+++ b/springboot-petclinic-client/src/scripts/visits/visits.js
@@ -0,0 +1,11 @@
+'use strict';
+
+angular.module('visits', ['ui.router'])
+    .config(['$stateProvider', function ($stateProvider) {
+        $stateProvider
+            .state('visits', {
+                parent: 'app',
+                url: '/owners/:ownerId/pets/:petId/visits',
+                template: '<visits></visits>'
+            })
+    }]);
diff --git a/springboot-petclinic-server/src/main/resources/templates/index.html b/springboot-petclinic-server/src/main/resources/templates/index.html
index 5d6429aab75c23e19352a7eff3399a7cb5746870..441679f9736d018013c4252fce17813d5e3b93e2 100644
--- a/springboot-petclinic-server/src/main/resources/templates/index.html
+++ b/springboot-petclinic-server/src/main/resources/templates/index.html
@@ -18,24 +18,41 @@
     <script th:src="@{/jquery/jquery.min.js}"></script>
     <script th:src="@{/bootstrap/js/bootstrap.min.js}"></script>
 
-    <script th:src="@{/angular/angular.min.js}"></script>
-    <script th:src="@{/angular-route/angular-route.min.js}"></script>
+    <script th:src="@{/angular/angular.js}"></script>
+    <script th:src="@{/angular-ui-router/release/angular-ui-router.min.js}"></script>
 
     <script th:src="@{/scripts/app.js}"></script>
+
+    <script th:src="@{/scripts/owner-list/owner-list.js}"></script>
+    <script th:src="@{/scripts/owner-list/owner-list.controller.js}"></script>
     <script th:src="@{/scripts/owner-list/owner-list.component.js}"></script>
+
+    <script th:src="@{/scripts/owner-details/owner-details.js}"></script>
+    <script th:src="@{/scripts/owner-details/owner-details.controller.js}"></script>
     <script th:src="@{/scripts/owner-details/owner-details.component.js}"></script>
+
+    <script th:src="@{/scripts/owner-form/owner-form.js}"></script>
+    <script th:src="@{/scripts/owner-form/owner-form.controller.js}"></script>
     <script th:src="@{/scripts/owner-form/owner-form.component.js}"></script>
+
+    <script th:src="@{/scripts/pet-form/pet-form.js}"></script>
+    <script th:src="@{/scripts/pet-form/pet-form.controller.js}"></script>
     <script th:src="@{/scripts/pet-form/pet-form.component.js}"></script>
+
+    <script th:src="@{/scripts/visits/visits.js}"></script>
+    <script th:src="@{/scripts/visits/visits.controller.js}"></script>
     <script th:src="@{/scripts/visits/visits.component.js}"></script>
-    <script th:src="@{/scripts/vet-list/vet-list.component.js}"></script>
 
+    <script th:src="@{/scripts/vet-list/vet-list.js}"></script>
+    <script th:src="@{/scripts/vet-list/vet-list.controller.js}"></script>
+    <script th:src="@{/scripts/vet-list/vet-list.component.js}"></script>
 </head>
 
 <body class="container">
 <layout-nav></layout-nav>
 <div class="container-fluid">
     <div class="container xd-container">
-        <div ng-view=""></div>
+        <div ui-view=""></div>
     </div>
 </div>
 <layout-footer></layout-footer>