Skip to content

Instantly share code, notes, and snippets.

@renoirb
Forked from anonymous/index.html
Created September 30, 2016 19:44
Show Gist options
  • Save renoirb/5524afa1e0a28304cd6ed5e29812630f to your computer and use it in GitHub Desktop.
Save renoirb/5524afa1e0a28304cd6ed5e29812630f to your computer and use it in GitHub Desktop.
Renoir's Challenge Use an JSON object to describe a form // source http://jsbin.com/kavume
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Renoir's Challenge</title>
<meta name="description" content="Use an JSON object to describe a form" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="https://npmcdn.com/api-check@latest/dist/api-check.js"></script>
<script src="https://npmcdn.com/[email protected]/dist/formly.js"></script>
<script src="https://npmcdn.com/[email protected]/dist/angular-formly-templates-bootstrap.js"></script>
</head>
<body ng-app="renoirChallenge" ng-controller="UserProfileCtrl as view">
<div class="container">
<h1>{{::view.title}}</h1>
<form ng-submit="view.onSubmit()" name="view.form" novalidate>
<formly-form model="view.model" fields="view.fields" options="view.options" form="view.form">
<div class=well>
<button type="submit" class="btn btn-primary submit-button" ng-disabled="view.form.$invalid">Submit</button>
<button type="button" class="btn btn-default" ng-click="view.options.resetModel()">Reset</button>
</div>
</formly-form>
</form>
<h2>Form Data</h2>
<pre>{{view.model | json}}</pre>
</div>
<script id="jsbin-javascript">
/*jshint esnext: true */
/*global angular */
/**
* Renoir's challenge
*
* Use input JSON object to describe a form.
*
* Relevant help I used:
* - http://angular-formly.com/
* - https://hacks.mozilla.org/2015/08/es6-in-depth-modules/
* - http://www.michaelbromley.co.uk/blog/350/exploring-es6-classes-in-angularjs-1-x
* - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
* - http://stackoverflow.com/questions/32113604/why-is-the-new-es6-find-method-not-recognised-in-jsbin
**/
"use strict";
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
console.clear();
var inputs = {
"email": {
"docs": "Email address of the user. Used for authentication. Must be unique.",
"type": "Text",
"presentation": {
"label": "Email",
"type": "email",
"order": 1
},
"validation": {
"required": true
}
},
"password": {
"docs": "Encoded user password. Used for authentication. Write unencoded, saves encoded.",
"type": "Text",
"presentation": {
"label": "Password",
"type": "password",
"order": 2
}
},
"fullName": {
"docs": "Human's full name. For client display and human readability",
"type": "Text",
"presentation": {
"label": "Full Name",
"visible": "none",
"order": 9
},
"validation": {
"required": true
}
},
"firstName": {
"docs": "Human's first name. For client display and human readability.",
"type": "Text",
"presentation": {
"label": "First Name",
"order": 3
},
"validation": {
"minLen": 1,
"maxLen": 50
}
},
"lastName": {
"docs": "Human's last name. For client display and human readability.",
"type": "Text",
"presentation": {
"label": "Last Name",
"order": 4
},
"validation": {
"minLen": 1,
"maxLen": 50
}
}
};
{
var validFieldTypes;
(function () {
/**
* Prepare field prior to add them to controller fields
*
* Where we can SwitchCase logic we may want to add.
**/
var prepareField = function prepareField(field, orig) {
var fType = validFieldTypes.find(function (v) {
return orig.presentation.type === v;
}) || null;
if (!!fType) {
field.templateOptions.type = fType;
}
// Lets cut some corners now. sorry about that!
if (!!orig.validation) {
if (!!orig.validation.minLen) {
field.templateOptions.minlength = orig.validation.minLen;
}
if (!!orig.validation.maxLen) {
field.templateOptions.maxlength = orig.validation.maxLen;
}
if (!!orig.validation.required) {
field.templateOptions.required = true;
}
}
return field;
};
/**
* ECMAScript 2015 FTW!
*
* This *IS* a Module, and implicitly in strict mode
**/
validFieldTypes = ['email', 'password'];
var UserProfile = (function () {
function UserProfile() {
_classCallCheck(this, UserProfile);
this.title = 'Your profile';
this.model = {};
this.options = {};
var fields = {},
ordering = [];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = Object.keys(inputs)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var k = _step.value;
var iter = inputs[k],
dto = { templateOptions: {} };
dto.key = k;
// Did not see use of any other input types
dto.type = 'input';
dto.templateOptions.label = iter.presentation.label;
// I was unsure if you wanted this text there or not.
dto.templateOptions.description = iter.docs;
// I assumed order was ALWAYS there. Maybe I should not trust blindly
ordering[Number(iter.presentation.order)] = k;
fields[k] = prepareField(dto, iter);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator["return"]) {
_iterator["return"]();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
ordering = ordering.filter(function (v) {
return v !== undefined;
});
this.fields = ordering.map(function (currentValue) {
return fields[currentValue];
});
}
_createClass(UserProfile, [{
key: "onSubmit",
value: function onSubmit() {
alert(JSON.stringify(this.model), null, 2);
}
}]);
return UserProfile;
})();
angular.module('renoirChallenge', ['formly', 'formlyBootstrap']).controller('UserProfileCtrl', UserProfile);
})();
}
</script>
<script id="jsbin-source-html" type="text/html"><!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Renoir's Challenge</title>
<meta name="description" content="Use an JSON object to describe a form" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"><\/script>
<script src="https://npmcdn.com/api-check@latest/dist/api-check.js"><\/script>
<script src="https://npmcdn.com/[email protected]/dist/formly.js"><\/script>
<script src="https://npmcdn.com/[email protected]/dist/angular-formly-templates-bootstrap.js"><\/script>
</head>
<body ng-app="renoirChallenge" ng-controller="UserProfileCtrl as view">
<div class="container">
<h1>{{::view.title}}</h1>
<form ng-submit="view.onSubmit()" name="view.form" novalidate>
<formly-form model="view.model" fields="view.fields" options="view.options" form="view.form">
<div class=well>
<button type="submit" class="btn btn-primary submit-button" ng-disabled="view.form.$invalid">Submit</button>
<button type="button" class="btn btn-default" ng-click="view.options.resetModel()">Reset</button>
</div>
</formly-form>
</form>
<h2>Form Data</h2>
<pre>{{view.model | json}}</pre>
</div>
</body>
</html>
</script>
<script id="jsbin-source-javascript" type="text/javascript">/*jshint esnext: true */
/*global angular */
/**
* Renoir's challenge
*
* Use input JSON object to describe a form.
*
* Relevant help I used:
* - http://angular-formly.com/
* - https://hacks.mozilla.org/2015/08/es6-in-depth-modules/
* - http://www.michaelbromley.co.uk/blog/350/exploring-es6-classes-in-angularjs-1-x
* - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
* - http://stackoverflow.com/questions/32113604/why-is-the-new-es6-find-method-not-recognised-in-jsbin
**/
console.clear();
var inputs = {
"email":{
"docs":"Email address of the user. Used for authentication. Must be unique.",
"type":"Text",
"presentation" : {
"label":"Email",
"type":"email",
"order":1
},
"validation" : {
"required" : true
}
},
"password":{
"docs":"Encoded user password. Used for authentication. Write unencoded, saves encoded.",
"type":"Text",
"presentation" : {
"label":"Password",
"type": "password",
"order":2
}
},
"fullName" : {
"docs" : "Human's full name. For client display and human readability",
"type" : "Text",
"presentation" : {
"label" : "Full Name",
"visible":"none",
"order":9
},
"validation" : {
"required" : true
}
},
"firstName":{
"docs":"Human's first name. For client display and human readability.",
"type":"Text",
"presentation" : {
"label":"First Name",
"order":3
},
"validation" : {
"minLen":1,
"maxLen":50
}
},
"lastName":{
"docs":"Human's last name. For client display and human readability.",
"type":"Text",
"presentation" : {
"label":"Last Name",
"order":4
},
"validation" : {
"minLen":1,
"maxLen":50
}
}
};
{
/**
* ECMAScript 2015 FTW!
*
* This *IS* a Module, and implicitly in strict mode
**/
var validFieldTypes = ['email','password'];
/**
* Prepare field prior to add them to controller fields
*
* Where we can SwitchCase logic we may want to add.
**/
function prepareField(field, orig) {
let fType = validFieldTypes.find( v => orig.presentation.type === v ) || null;
if (!!fType) {
field.templateOptions.type = fType;
}
// Lets cut some corners now. sorry about that!
if (!!orig.validation) {
if (!!orig.validation.minLen) {
field.templateOptions.minlength = orig.validation.minLen;
}
if (!!orig.validation.maxLen) {
field.templateOptions.maxlength = orig.validation.maxLen;
}
if (!!orig.validation.required) {
field.templateOptions.required = true;
}
}
return field;
}
class UserProfile {
constructor() {
this.title = 'Your profile';
this.model = {};
this.options = {};
let fields = {},
ordering = [];
for (let k of Object.keys(inputs)) {
let iter = inputs[k]
, dto = {templateOptions:{}};
dto.key = k;
// Did not see use of any other input types
dto.type = 'input';
dto.templateOptions.label = iter.presentation.label;
// I was unsure if you wanted this text there or not.
dto.templateOptions.description = iter.docs;
// I assumed order was ALWAYS there. Maybe I should not trust blindly
ordering[Number(iter.presentation.order)] = k;
fields[k] = prepareField(dto, iter);
}
ordering = ordering.filter(v => v !== undefined);
this.fields = ordering.map( currentValue => fields[currentValue] );
}
onSubmit() {
alert(JSON.stringify(this.model), null, 2);
}
}
angular
.module('renoirChallenge', [
'formly'
,'formlyBootstrap'
])
.controller('UserProfileCtrl', UserProfile);
}</script></body>
</html>
/*jshint esnext: true */
/*global angular */
/**
* Renoir's challenge
*
* Use input JSON object to describe a form.
*
* Relevant help I used:
* - http://angular-formly.com/
* - https://hacks.mozilla.org/2015/08/es6-in-depth-modules/
* - http://www.michaelbromley.co.uk/blog/350/exploring-es6-classes-in-angularjs-1-x
* - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
* - http://stackoverflow.com/questions/32113604/why-is-the-new-es6-find-method-not-recognised-in-jsbin
**/
"use strict";
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
console.clear();
var inputs = {
"email": {
"docs": "Email address of the user. Used for authentication. Must be unique.",
"type": "Text",
"presentation": {
"label": "Email",
"type": "email",
"order": 1
},
"validation": {
"required": true
}
},
"password": {
"docs": "Encoded user password. Used for authentication. Write unencoded, saves encoded.",
"type": "Text",
"presentation": {
"label": "Password",
"type": "password",
"order": 2
}
},
"fullName": {
"docs": "Human's full name. For client display and human readability",
"type": "Text",
"presentation": {
"label": "Full Name",
"visible": "none",
"order": 9
},
"validation": {
"required": true
}
},
"firstName": {
"docs": "Human's first name. For client display and human readability.",
"type": "Text",
"presentation": {
"label": "First Name",
"order": 3
},
"validation": {
"minLen": 1,
"maxLen": 50
}
},
"lastName": {
"docs": "Human's last name. For client display and human readability.",
"type": "Text",
"presentation": {
"label": "Last Name",
"order": 4
},
"validation": {
"minLen": 1,
"maxLen": 50
}
}
};
{
var validFieldTypes;
(function () {
/**
* Prepare field prior to add them to controller fields
*
* Where we can SwitchCase logic we may want to add.
**/
var prepareField = function prepareField(field, orig) {
var fType = validFieldTypes.find(function (v) {
return orig.presentation.type === v;
}) || null;
if (!!fType) {
field.templateOptions.type = fType;
}
// Lets cut some corners now. sorry about that!
if (!!orig.validation) {
if (!!orig.validation.minLen) {
field.templateOptions.minlength = orig.validation.minLen;
}
if (!!orig.validation.maxLen) {
field.templateOptions.maxlength = orig.validation.maxLen;
}
if (!!orig.validation.required) {
field.templateOptions.required = true;
}
}
return field;
};
/**
* ECMAScript 2015 FTW!
*
* This *IS* a Module, and implicitly in strict mode
**/
validFieldTypes = ['email', 'password'];
var UserProfile = (function () {
function UserProfile() {
_classCallCheck(this, UserProfile);
this.title = 'Your profile';
this.model = {};
this.options = {};
var fields = {},
ordering = [];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = Object.keys(inputs)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var k = _step.value;
var iter = inputs[k],
dto = { templateOptions: {} };
dto.key = k;
// Did not see use of any other input types
dto.type = 'input';
dto.templateOptions.label = iter.presentation.label;
// I was unsure if you wanted this text there or not.
dto.templateOptions.description = iter.docs;
// I assumed order was ALWAYS there. Maybe I should not trust blindly
ordering[Number(iter.presentation.order)] = k;
fields[k] = prepareField(dto, iter);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator["return"]) {
_iterator["return"]();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
ordering = ordering.filter(function (v) {
return v !== undefined;
});
this.fields = ordering.map(function (currentValue) {
return fields[currentValue];
});
}
_createClass(UserProfile, [{
key: "onSubmit",
value: function onSubmit() {
alert(JSON.stringify(this.model), null, 2);
}
}]);
return UserProfile;
})();
angular.module('renoirChallenge', ['formly', 'formlyBootstrap']).controller('UserProfileCtrl', UserProfile);
})();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment