<!DOCTYPE html>
<html ng-app="superForm">
<head>
  <meta charset="utf-8" />
  <title>AngularJS superForm</title>
  <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" />
  <script>
  document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script src="https://code.angularjs.org/1.2.10/angular.js" data-semver="1.2.10"></script>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular-animate.min.js"></script>
  <script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>
  <script src="app.js"></script>
</head>
<body ng-controller="MainCtrl" id="body">
  <div class="animate-switch-container" ng-switch on="selection" 
       ng-class="{forward: direction, backward:!direction,longStage: longStage}">

    <div class="animate-switch"  ng-switch-default>
      <form name="form" role="form" novalidate="" class="formClass">
        <div class="row">
          <div class="col-xs-6">
            <div class="form-group" ng-class="{'has-error':  form.uName.$invalid, 'has-success': !form.uName.$invalid}">
              <label for="uName ">User Name</label>
              <input type="text " class="form-control " name="uName " placeholder="User Name " ng-model="user.name " required=" " />
              <div class="err_tip " ng-show="form.uName.$dirty && form.uName.$invalid ">
                <span ng-show="form.uName.$error.required ">User name is required.</span>
              </div>
            </div>
          </div>
          <div class="col-xs-6 ">
            <div class="form-group " ng-class="{ 'has-error':  form.uEmail.$invalid, 'has-success': !form.uEmail.$invalid}">
              <label for="uEmail">Email address</label>
              <input type="email" class="form-control" name="uEmail" placeholder="Enter email" ng-model="user.email" required="" />
              <div class="err_tip" ng-show="form.uEmail.$dirty && form.uEmail.$invalid">
                <span ng-show="form.uEmail.$error.required">This field is required.</span>
                <span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
              </div>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="col-xs-6">
            <div class="form-group" ng-class="{'has-error':  form.uPass.$invalid, 'has-success': !form.uPass.$invalid}">
              <label for="uPass ">Password</label>
              <input type="password" class="form-control" name="uPass" placeholder="Password "  ng-model="user.pass " required=" " ng-pattern="/^(?=.*\d)(?=.*\D).{6,}$/"/>
              <div class="err_tip " ng-show="form.uPass.$dirty && form.uPass.$invalid ">
                <span ng-show="form.uPass.$error.required ">Password is required.</span>
                <span ng-show="form.uPass.$error.pattern">Password must contain at least one digit and one letter and be at least 6 characters.</span>
              </div>
            </div>
          </div>
          <div class="col-xs-6 ">
            <div class="form-group " ng-class="{ 'has-error':  form.uPassConf.$invalid, 'has-success': !form.uPassConf.$invalid}">
              <label for="uPassConf">Confirm Password</label>
              <input type="password" class="form-control" name="uPassConf" placeholder="Confirm Password" ng-model="user.passconf" required="" password-match="user.pass" />
              <div class="err_tip" ng-show="form.uPassConf.$dirty && form.uPassConf.$invalid">
                <span ng-show="form.uPassConf.$error.required">This field is required.</span>
                <span ng-show="form.uPassConf.$error.unique">Password does not match the confirm password.</span>
              </div>
            </div>
          </div>
        </div>
        <button class="btn" ng-click="update(user,'stage2')" ng-disabled="form.$invalid" ng-class="{'btn-danger': form.$invalid, 'btn-success': !form.$invalid } ">Next</button>
      </form>
    </div>

    <div class="animate-switch" ng-switch-when="stage2">
      <form name="form" role="form" novalidate="" class="formClass">
        <div class="row">
          <div class="col-xs-8">
            <div class="form-group " ng-class="{ 'has-error':  form.uSecQuest.$invalid, 'has-success': !form.uSecQuest.$invalid}">
              <label for="uSecQuest">Security Questions</label>
              <select class="form-control"   name="uSecQuest" required="" ng-options="c.quest for c in questions"  ng-model="user.secQuest">
                <option value="">-- Choose Security Questions --</option>
              </select>
            </div>
          </div>
  <!--    <div class="col-xs-4">
            {{questions | json}}
          </div> -->
        </div>
        <button class="btn btn-primary" ng-click="backTo('default')">Back</button>
        <button class="btn" ng-click="pushToServer(user)" ng-disabled="form.$invalid " ng-class="{'btn-danger': form.$invalid, 'btn-success': !form.$invalid } ">Next</button>
      </form>
    </div>

    <div class="animate-switch" ng-switch-when="finish">
        <div class="row">
          <div class="col-xs-12 fade"  ng-class="{in:longStage}">
            <pre>form = {{user | json}}</pre>
            <pre>master = {{master | json}}</pre>
          </div>
        </div>
    </div>
          <a id="blog" target="_blank" href="https://kwakwak-code.blogspot.co.il/">My Blog</a>
  </div>
</body>
</html>

#body {
  background-color: #BFBAAF;
  margin:20px;
}
.animate-switch-container.forward.longStage  {
  transition:all 0.5s;
  height: 500px;
}

.fade {
  opacity: 0;
  -webkit-transition: opacity 0.25s ease-in;
  -moz-transition: opacity 0.25s ease-in;
  -o-transition: opacity 0.25s ease-in;
  -ms-transition: opacity 0.25s ease-in;
  transition: opacity 0.25s ease-in;
  transition-delay: 0.25s;
}
.fade.in{
  opacity: 1;
}

.animate-switch-container {
  position:relative;
  overflow: hidden;
  height: 300px;
  width: 550px;
  border: solid 1px black;
  box-shadow: 6px 6px 15px gray;
  padding:10px;
  border-radius:10px;

  background-color: #D1E5D3;
  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, rgba(0, 0, 0, 0) 25%, rgba(0, 0, 0, 0) 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, rgba(0, 0, 0, 0) 75%, rgba(0, 0, 0, 0));
  background-size: 50px 50px;
}
.animate-switch{
  padding:10px;
  width: 100%;
}
.animate-switch.ng-animate {
  -webkit-transition:all 0.5s;
  transition:all 0.5s;
  position:absolute;

}
/* hide leaving slide  */
/* show */
.animate-switch.ng-leave{  
  left:0;
}
/* hide */
.forward .animate-switch.ng-leave.ng-leave-active{ 
  left:-100%;
}
.backward .animate-switch.ng-leave.ng-leave-active{ 
  left: 100%;
}
/* show entering slide  */
/* hide */
.forward .animate-switch.ng-enter {
  left:100%;
}
.backward .animate-switch.ng-enter {
  left:-100%;
}
/* show */
.animate-switch.ng-enter.ng-enter-active { 
  left:0;
}

/*Error Tooltip */
.err_tip {
  position: absolute;
  bottom: 50px;
  right: 0px;
  width: 200px;
  background-color: #DA362A;
  color: white;
  padding: 2px;
  border-radius: 16px;
  box-shadow: 3px 3px 10px #888888;
  margin: 5px;
  text-align: center;
  border: 2px solid #000000;
  z-index: 1;
}
.err_tip:after, .err_tip:before {
  top: 100%;
  left: 50%;
  border: solid transparent;
  content: " ";
  height: 0;
  width: 0;
  position: absolute;
  pointer-events: none;
}
.err_tip:after {
  border-color: rgba(218, 54, 42, 0);
  border-top-color: #DA362A;
  border-width: 10px;
  margin-left: -10px;
}
.err_tip:before {
  border-color: rgba(0, 0, 0, 0);
  border-top-color: #000000;
  border-width: 13px;
  margin-left: -13px;
}

#blog{
  position: absolute;
  bottom: 10px;
  right: 10px;
}
'use strict';
var app = angular.module('superForm', ['ngAnimate']);

/* Controllers */
function MainCtrl($scope, $http) {
  $scope.fetchSecQuestUrl ='http://www.mocky.io/v2/52ea5a9a7cf0cd6806540819?callback=JSON_CALLBACK';
    $scope.pushToServerUrl ='http://www.mocky.io/v2/52f0f1bdbf227b1603d8a146?callback=JSON_CALLBACK'; //true
//  $scope.pushToServerUrl ='http://www.mocky.io/v2/52f0f29dbf227b2103d8a147?callback=JSON_CALLBACK'; //false

  $scope.master = {
    name: "Ronny",
    pass: "1q2w3e",
    passconf: "1q2w3e",
    email: "ronihcohen@gmail.com",
  };

  $scope.longStage = 0;
  $scope.update = function(user,nextStage) {
    $scope.master = angular.copy(user);
    $scope.direction = 1;
    $scope.selection = nextStage;
    if (nextStage=="stage3"){
      $scope.longStage = 1;
    }
  };
  $scope.reset = function() {
    $scope.user = angular.copy($scope.master);
  };
  $scope.reset();

  $scope.isUnchanged = function(user) {
    return angular.equals(user, $scope.master);
  };

  $scope.backTo = function(stage) {
    $scope.direction = 0;
    $scope.selection = stage;
  };

  $scope.fetchSecQuest = function() {
    $scope.code = null;
    $scope.response = null;
    // cache set to false for IE
    var httpHeaders = { 'If-Modified-Since': "0" };
    // Data sent to the server
    var myParams = {a:"q",did:"1",l:"ja-jp"};
    $http({
      method: 'JSONP',
      url: $scope.fetchSecQuestUrl,
      cache: false,
      headers: httpHeaders,
      params: myParams
    }).
    success(function(data, status) {
      // pre-selecting question two
      $scope.questions = data.questions;
      $scope.user.secQuest= $scope.questions[1];
    }).
    error(function(data, status) {
      $scope.questions = data.questions || "Request failed";
      $scope.status = status;
    });
  };


  $scope.pushToServer = function(user) {
    $scope.master = angular.copy(user);

    $scope.code = null;
    $scope.response = null;
    // cache set to false for IE
    var httpHeaders = { 'If-Modified-Since': "0" };
    // Data sent to the server
    var myParams = $scope.master;
    $http({
      method: 'JSONP',
      url: $scope.pushToServerUrl,
      cache: false,
      headers: httpHeaders,
      params: myParams
    }).
    success(function(data, status) {
      if (data.suc===true){
        $scope.direction = 1;
        $scope.longStage = 1;
        $scope.selection = "finish";
      } else if (data.suc===false) {
        console.log (data.suc);
      }
    }).
    error(function(data, status) {
      console.log ("pushToServer: Request failed");
      $scope.status = status;
    });
  };

  $scope.fetchSecQuest();

};

/* Directives */
app.directive('passwordMatch', [
  function() {
    return {
      restrict: 'A',
      scope: true,
      require: 'ngModel',
      link: function(scope, elem, attrs, control) {
        var checker = function() {
//get the value of the first password
var e1 = scope.$eval(attrs.ngModel);
//get the value of the other password  
var e2 = scope.$eval(attrs.passwordMatch);
return e1 == e2;
};
scope.$watch(checker, function(n) {
//set the form control to valid if both 
//passwords are the same, else invalid
control.$setValidity("unique", n);
});
}
};
}
]);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.