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>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.min.js"></script>
<h4>Angular-xeditable Editable form (Bootstrap 3)</h4>
<div ng-app="app" ng-controller="Ctrl">
 <form editable-form name="editableForm" onaftersave="saveUser()">
    <div>
      <!-- editable username (text with validation) -->
      <span class="title">User name: </span>
      <span editable-text="user.name" e-name="name" onbeforesave="checkName($data)" e-required>{{ user.name || 'empty' }}</span>
    </div> 

    <div>
      <!-- editable status (select-local) -->
      <span class="title">Status: </span>
      <span editable-select="user.status" e-name="status" e-ng-options="s.value as s.text for s in statuses">
        {{ (statuses | filter:{value: user.status})[0].text || 'Not set' }}
      </span>
    </div>
    
    <div>
      <!-- editable status (select-local) -->
      <span class="title">Date: </span>
      <span editable-bsdate="user.date" e-is-open="datePickerOpened.$data" e-ng-click="openDatePicker($event, '$data')"  e-datepicker-popup="dd-MMMM-yyyy" e-name="date">
        {{ (date | date:'dd-MM-yyyy') || 'Not set' }}
      </span>
    </div>  

    <div>
      <!-- editable group (select-remote) -->
      <span class="title">Group: </span>
      <span editable-select="user.group" e-name="group" onshow="loadGroups()" e-ng-options="g.id as g.text for g in groups">
        {{ showGroup() }}
...

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

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

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

app.controller('Ctrl', function($scope, $filter, $http) {
 $scope.user = {
    id: 1,
    name: 'awesome user',
    status: 2,
    date: new Date(),
    group: 4,
    groupName: 'admin'
  }; 
  $scope.datePickerOpened = {};

  $scope.statuses = [
    {value: 1, text: 'status1'},
    {value: 2, text: 'status2'},
    {value: 3, text: 'status3'},
    {value: 4, text: 'status4'}
  ]; 

  $scope.groups = [];
  $scope.loadGroups = function() {
    return $scope.groups.length ? null : $http.get('/groups').success(function(data) {
      $scope.groups = data;
    });
  };
  
  $scope.openDatePicker = function($event, elementOpened) {
			$event.preventDefault();
			$event.stopPropagation();

			$scope.datePickerOpened[elementOpened] = !$scope.datePickerOpened[elementOpened];
		}

  $scope.showGroup = function() {
    if($scope.groups.length) {
      var selected = $filter('filter')($scope.groups, {id: $scope.user.group});
      return selected.length ? selected[0].text : 'Not set';
    } else {
      return $scope.user.groupName;
    }
  };

  $scope.checkName = function(data) {
    if (data !== 'awesome' && data !== 'error') {
      return "Username should be `awesome` or `error`";
    }
  };

  $scope.saveUser = function() {
    // $scope.user already updated!
    return $http.post('/saveUser', $scope.user).error(function(err) {
      if(err.field && err.msg) {
        // err like {field: "name", msg: "Server-side error for this username!"} 
        $scope.editableForm.$setError(err.field, err.msg);
      } else { 
        // unknown error
        $scope.editableForm.$setError('name', 'Unknown error!');
      }
    });
  };
});

// ---------------- mock $http requests --------------------
app.run(function($httpBackend) {
  $httpBackend.whenGET('/groups').respond([
    {id: 1, text: 'user'},
    {id: 2, text: 'customer'},
...