JSFiddle - React, Tailwind, and code Playground

by ckosloski

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-sanitize.min.js"></script>
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="http://vitalets.github.io/angular-xeditable/dist/js/xeditable.js"></script>
<link rel="stylesheet" href="http://vitalets.github.io/angular-xeditable/dist/css/xeditable.css">
<script src="https://code.angularjs.org/1.5.8/angular-mocks.js"></script>
<h4>Angular-xeditable Editable form (Bootstrap 3)</h4>
<div ng-app="app" ng-controller="Ctrl">
 <form editable-form name="editableForm" onaftersave="saveUser()" onbeforesave="saveSeconds($data)">
    <div>
      <div duration-editor total-seconds="validatyPeriod"/>
    </div>
    <div>
      <!-- button to show form -->
      <button type="button" class="btn btn-default" ng-click="editableForm.$show()" ng-show="!editableForm.$visible">
        Edit
      </button>
      <!-- buttons to submit / cancel form -->
      <span ng-show="editableForm.$visible">
        <button type="submit" class="btn btn-primary" ng-disabled="editableForm.$waiting">
          Save
        </button>
        <button type="button" class="btn btn-default" ng-disabled="editableForm.$waiting" ng-click="editableForm.$cancel()">
          Cancel
        </button>
      </span>
    </div>
  </form>  
</div>
<script type="text/ng-template" id="partials/duration.html">
    <div class="input-group">
      <p class="form-control-static" editable-number="duration.days" e-class="form-control" e-ng-change="recaculate($data)">{{duration.days}}</p>
      <div class="input-group-addon">天</div>
      <p class="form-control-static" editable-number="duration.hours" e-class="form-control">{{duration.hours}}</p>
      <div class="input-group-addon">时</div>
      <p class="form-control-static" editable-number="duration.minutes"...

CSS

div[ng-app] { margin: 10px; }
form[name="editableForm"] > div {
  height: auto;
  padding: 5px 0;
}

form[name="editableForm"] .title {
  display: inline-block;
  font-weight: bold;
  padding-top: 5px;
  vertical-align: top;
  min-width: 90px;
}

form[name="editableForm"] .editable {
  display: inline-block;
  padding-top: 5px;
  vertical-align: top;
}

form[name="editableForm"] select {
  width: 120px;
}

JavaScript

class Duration {
    constructor(totalSeconds) {
		this.totalSeconds = totalSeconds;
    }

    get days() {
		return this._days;
    }

    set days(days) {
		this._days = days;
    }

    get hours() {
		return this._hours;
    }

    set hours(hours) {
		this._hours = hours;
    }

    get minutes() {
		return this._minutes;
    }

    set minutes(minutes) {
		this._minutes = minutes;
    }

    get seconds() {
		return this._seconds;
    }

    set seconds(seconds) {
		this._seconds = seconds;
    }

    get totalSeconds() {
		var value = this._days;
		value = value * 24 + this._hours;
		value = value * 60 + this._minutes;
		value = value * 60 + this._seconds;
		return value;
    }

    set totalSeconds(totalSeconds) {
		var value = totalSeconds;
		this._seconds = value % 60;
		value = Math.floor(value / 60);
		this._minutes = value % 60;
		value = Math.floor(value / 60);
		this._hours = value % 24;
		value = Math.floor(value / 24);
		this._days = value;
    }
}

var app = angular.module("app", ["xeditable", "ngMockE2E"]);

app.run(function(editableOptions) {
  editableOptions.theme = 'bs3';
});

app.controller('Ctrl', function($scope, $filter, $http) {
 $scope.validatyPeriod = 61;

 $scope.saveUser = function() {
 console.log("saveUser");
 setTimeout(function () {
    alert("validatyPeriod: " + $scope.validatyPeriod + " seconds");
  }, 100);
		
  };
  $scope.saveSeconds = function($data) {
  console.log($data.toString());
		//$scope.totalSeconds = $scope.duration.totalSeconds;
  };
});

app.directive('durationEditor', [function () {
    return {
        restrict: 'AE',
        scope: {
            totalSeconds: '='
        },
        link: function(scope, element, attrs) {
			scope.duration = new Duration(0);
			scope.$watch('totalSeconds', function () {
				scope.duration.totalSeconds = scope.totalSeconds;
            });
			scope.$watch('duration', function () {
      console.log("watch");
				scope.totalSeconds = scope.duration.totalSeconds;
			},...