├── .babelrc ├── .gitignore ├── .jshintrc ├── README.md ├── dist ├── app.66f9fcf1.js ├── app.66f9fcf1.js.map ├── index.html ├── styles.c6edcaf7.css ├── styles.c6edcaf7.css.map └── success.html ├── package-lock.json ├── package.json └── src ├── css └── styles.css ├── index.html ├── js ├── app.js └── service │ └── FetchService.js └── success.html /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | [ 4 | "@babel/plugin-transform-runtime", 5 | { 6 | "regenerator": true 7 | } 8 | ] 9 | ] 10 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .cache -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esversion": 8 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Submitting Forms to JSON APIs 2 | ## Introduction 3 | This is the source code for the blog post explaining an easy and clean way to submit HTML forms to JSON APIs. 4 | ## Project 5 | - Technology: HTML, CSS, JavaScript. 6 | - API Communication: Used fetch to communicate with the API. 7 | ## How To Run 8 | 1. Clone or download the repository. 9 | 2. Open the project containing folder in a terminal or a text editor like VS Code. 10 | 3. Run `npm install`. 11 | 4. Run `npm run dev` for development or `npm run build` for deployment. 12 | ## Article 13 | The article can be found here: 14 | [https://dev.to/amjadmh73/submit-html-forms-to-json-apis-easily-137l](https://dev.to/amjadmh73/submit-html-forms-to-json-apis-easily-137l) -------------------------------------------------------------------------------- /dist/app.66f9fcf1.js: -------------------------------------------------------------------------------- 1 | parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;c=0;--i){var a=this.tryEntries[i],c=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var u=n.call(a,"catchLoc"),h=n.call(a,"finallyLoc");if(u&&h){if(this.prev=0;--e){var o=this.tryEntries[e];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--r){var e=this.tryEntries[r];if(e.finallyLoc===t)return this.complete(e.completion,e.afterLoc),k(e),v}},catch:function(t){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.tryLoc===t){var n=e.completion;if("throw"===n.type){var o=n.arg;k(e)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:N(t),resultName:e,nextLoc:n},"next"===this.method&&(this.arg=r),v}},t}("object"==typeof module?module.exports:{});try{regeneratorRuntime=r}catch(e){Function("r","regeneratorRuntime = r")(r)} 4 | },{}],"PMvg":[function(require,module,exports) { 5 | module.exports=require("regenerator-runtime"); 6 | },{"regenerator-runtime":"QVnC"}],"agGE":[function(require,module,exports) { 7 | function n(n,t,o,r,e,i,u){try{var c=n[i](u),v=c.value}catch(a){return void o(a)}c.done?t(v):Promise.resolve(v).then(r,e)}function t(t){return function(){var o=this,r=arguments;return new Promise(function(e,i){var u=t.apply(o,r);function c(t){n(u,e,i,c,v,"next",t)}function v(t){n(u,e,i,c,v,"throw",t)}c(void 0)})}}module.exports=t; 8 | },{}],"fcMS":[function(require,module,exports) { 9 | function n(n,o){if(!(n instanceof o))throw new TypeError("Cannot call a class as a function")}module.exports=n; 10 | },{}],"P8NW":[function(require,module,exports) { 11 | function e(e,r){for(var n=0;n2&&void 0!==o[2]?o[2]:null,t&&n){e.next=3;break}throw new Error("One or more GET request parameters was not passed.");case 3:return e.prev=3,e.next=6,fetch(t,{method:"GET",headers:n,query:null!=a?a:""});case 6:return u=e.sent,e.next=9,u.json();case 9:return s=e.sent,e.abrupt("return",s);case 13:throw e.prev=13,e.t0=e.catch(3),console.error("Error at fetch GET: ".concat(e.t0)),e.t0;case 17:case"end":return e.stop()}},r,null,[[3,13]])}));return function(e,r){return t.apply(this,arguments)}}()},{key:"performPostHttpRequest",value:function(){var t=(0,r.default)(e.default.mark(function r(t,n,a){var u,s;return e.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(t&&n&&a){e.next=2;break}throw new Error("One or more POST request parameters was not passed.");case 2:return e.prev=2,e.next=5,fetch(t,{method:"POST",headers:n,body:JSON.stringify(a)});case 5:return u=e.sent,e.next=8,u.json();case 8:return s=e.sent,e.abrupt("return",s);case 12:throw e.prev=12,e.t0=e.catch(2),console.error("Error at fetch POST: ".concat(e.t0)),e.t0;case 16:case"end":return e.stop()}},r,null,[[2,12]])}));return function(e,r,n){return t.apply(this,arguments)}}()},{key:"performPutHttpRequest",value:function(){var t=(0,r.default)(e.default.mark(function r(t,n,a){var u,s;return e.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(t&&n&&a){e.next=2;break}throw new Error("One or more POST request parameters was not passed.");case 2:return e.prev=2,e.next=5,fetch(t,{method:"PUT",headers:n,body:JSON.stringify(a)});case 5:return u=e.sent,e.next=8,u.json();case 8:return s=e.sent,e.abrupt("return",s);case 12:throw e.prev=12,e.t0=e.catch(2),console.error("Error at fetch PUT: ".concat(e.t0)),e.t0;case 16:case"end":return e.stop()}},r,null,[[2,12]])}));return function(e,r,n){return t.apply(this,arguments)}}()}]),a}();exports.default=u; 14 | },{"@babel/runtime/regenerator":"PMvg","@babel/runtime/helpers/asyncToGenerator":"agGE","@babel/runtime/helpers/classCallCheck":"fcMS","@babel/runtime/helpers/createClass":"P8NW"}],"QdeU":[function(require,module,exports) { 15 | "use strict";var e=n(require("@babel/runtime/regenerator")),t=n(require("@babel/runtime/helpers/asyncToGenerator")),r=n(require("./service/FetchService"));function n(e){return e&&e.__esModule?e:{default:e}}function o(e,t){var r;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(r=a(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,o=function(){};return{s:o,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,u=!0,c=!1;return{s:function(){r=e[Symbol.iterator]()},n:function(){var e=r.next();return u=e.done,e},e:function(e){c=!0,i=e},f:function(){try{u||null==r.return||r.return()}finally{if(c)throw i}}}}function a(e,t){if(e){if("string"==typeof e)return i(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?i(e,t):void 0}}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r0&&void 0!==arguments[0]?arguments[0]:null;return{"Content-Type":"application/json",Authorization:e||"Bearer TOKEN_MISSING"}}function f(e){var t,r={},n=o(new FormData(e));try{for(n.s();!(t=n.n()).done;){var a=t.value;r[a[0]]=a[1]}}catch(i){n.e(i)}finally{n.f()}return r}var d=document.querySelector("#sampleForm");d&&d.addEventListener("submit",function(e){c(e,this)}); 16 | },{"@babel/runtime/regenerator":"PMvg","@babel/runtime/helpers/asyncToGenerator":"agGE","./service/FetchService":"g3E6"}]},{},["QdeU"], null) 17 | //# sourceMappingURL=/app.66f9fcf1.js.map -------------------------------------------------------------------------------- /dist/app.66f9fcf1.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../node_modules/regenerator-runtime/runtime.js","../node_modules/@babel/runtime/regenerator/index.js","../node_modules/@babel/runtime/helpers/asyncToGenerator.js","../node_modules/@babel/runtime/helpers/classCallCheck.js","../node_modules/@babel/runtime/helpers/createClass.js","js/service/FetchService.js","js/app.js"],"names":["FetchService","fetchLink","headers","query","Error","fetch","method","rawResponse","json","content","console","error","body","JSON","stringify","fetchService","submitForm","e","form","preventDefault","btnSubmit","document","getElementById","disabled","setTimeout","jsonFormData","buildJsonFormData","buildHeaders","performPostHttpRequest","response","log","window","location","FirstName","LastName","Email","id","alert","authorization","FormData","pair","sampleForm","querySelector","addEventListener"],"mappings":"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","file":"app.66f9fcf1.js","sourceRoot":"..\\src","sourcesContent":["/**\n * Copyright (c) 2014-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nvar runtime = (function (exports) {\n \"use strict\";\n\n var Op = Object.prototype;\n var hasOwn = Op.hasOwnProperty;\n var undefined; // More compressible than void 0.\n var $Symbol = typeof Symbol === \"function\" ? Symbol : {};\n var iteratorSymbol = $Symbol.iterator || \"@@iterator\";\n var asyncIteratorSymbol = $Symbol.asyncIterator || \"@@asyncIterator\";\n var toStringTagSymbol = $Symbol.toStringTag || \"@@toStringTag\";\n\n function define(obj, key, value) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n return obj[key];\n }\n try {\n // IE 8 has a broken Object.defineProperty that only works on DOM objects.\n define({}, \"\");\n } catch (err) {\n define = function(obj, key, value) {\n return obj[key] = value;\n };\n }\n\n function wrap(innerFn, outerFn, self, tryLocsList) {\n // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.\n var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;\n var generator = Object.create(protoGenerator.prototype);\n var context = new Context(tryLocsList || []);\n\n // The ._invoke method unifies the implementations of the .next,\n // .throw, and .return methods.\n generator._invoke = makeInvokeMethod(innerFn, self, context);\n\n return generator;\n }\n exports.wrap = wrap;\n\n // Try/catch helper to minimize deoptimizations. Returns a completion\n // record like context.tryEntries[i].completion. This interface could\n // have been (and was previously) designed to take a closure to be\n // invoked without arguments, but in all the cases we care about we\n // already have an existing method we want to call, so there's no need\n // to create a new function object. We can even get away with assuming\n // the method takes exactly one argument, since that happens to be true\n // in every case, so we don't have to touch the arguments object. The\n // only additional allocation required is the completion record, which\n // has a stable shape and so hopefully should be cheap to allocate.\n function tryCatch(fn, obj, arg) {\n try {\n return { type: \"normal\", arg: fn.call(obj, arg) };\n } catch (err) {\n return { type: \"throw\", arg: err };\n }\n }\n\n var GenStateSuspendedStart = \"suspendedStart\";\n var GenStateSuspendedYield = \"suspendedYield\";\n var GenStateExecuting = \"executing\";\n var GenStateCompleted = \"completed\";\n\n // Returning this object from the innerFn has the same effect as\n // breaking out of the dispatch switch statement.\n var ContinueSentinel = {};\n\n // Dummy constructor functions that we use as the .constructor and\n // .constructor.prototype properties for functions that return Generator\n // objects. For full spec compliance, you may wish to configure your\n // minifier not to mangle the names of these two functions.\n function Generator() {}\n function GeneratorFunction() {}\n function GeneratorFunctionPrototype() {}\n\n // This is a polyfill for %IteratorPrototype% for environments that\n // don't natively support it.\n var IteratorPrototype = {};\n IteratorPrototype[iteratorSymbol] = function () {\n return this;\n };\n\n var getProto = Object.getPrototypeOf;\n var NativeIteratorPrototype = getProto && getProto(getProto(values([])));\n if (NativeIteratorPrototype &&\n NativeIteratorPrototype !== Op &&\n hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {\n // This environment has a native %IteratorPrototype%; use it instead\n // of the polyfill.\n IteratorPrototype = NativeIteratorPrototype;\n }\n\n var Gp = GeneratorFunctionPrototype.prototype =\n Generator.prototype = Object.create(IteratorPrototype);\n GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;\n GeneratorFunctionPrototype.constructor = GeneratorFunction;\n GeneratorFunction.displayName = define(\n GeneratorFunctionPrototype,\n toStringTagSymbol,\n \"GeneratorFunction\"\n );\n\n // Helper for defining the .next, .throw, and .return methods of the\n // Iterator interface in terms of a single ._invoke method.\n function defineIteratorMethods(prototype) {\n [\"next\", \"throw\", \"return\"].forEach(function(method) {\n define(prototype, method, function(arg) {\n return this._invoke(method, arg);\n });\n });\n }\n\n exports.isGeneratorFunction = function(genFun) {\n var ctor = typeof genFun === \"function\" && genFun.constructor;\n return ctor\n ? ctor === GeneratorFunction ||\n // For the native GeneratorFunction constructor, the best we can\n // do is to check its .name property.\n (ctor.displayName || ctor.name) === \"GeneratorFunction\"\n : false;\n };\n\n exports.mark = function(genFun) {\n if (Object.setPrototypeOf) {\n Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);\n } else {\n genFun.__proto__ = GeneratorFunctionPrototype;\n define(genFun, toStringTagSymbol, \"GeneratorFunction\");\n }\n genFun.prototype = Object.create(Gp);\n return genFun;\n };\n\n // Within the body of any async function, `await x` is transformed to\n // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test\n // `hasOwn.call(value, \"__await\")` to determine if the yielded value is\n // meant to be awaited.\n exports.awrap = function(arg) {\n return { __await: arg };\n };\n\n function AsyncIterator(generator, PromiseImpl) {\n function invoke(method, arg, resolve, reject) {\n var record = tryCatch(generator[method], generator, arg);\n if (record.type === \"throw\") {\n reject(record.arg);\n } else {\n var result = record.arg;\n var value = result.value;\n if (value &&\n typeof value === \"object\" &&\n hasOwn.call(value, \"__await\")) {\n return PromiseImpl.resolve(value.__await).then(function(value) {\n invoke(\"next\", value, resolve, reject);\n }, function(err) {\n invoke(\"throw\", err, resolve, reject);\n });\n }\n\n return PromiseImpl.resolve(value).then(function(unwrapped) {\n // When a yielded Promise is resolved, its final value becomes\n // the .value of the Promise<{value,done}> result for the\n // current iteration.\n result.value = unwrapped;\n resolve(result);\n }, function(error) {\n // If a rejected Promise was yielded, throw the rejection back\n // into the async generator function so it can be handled there.\n return invoke(\"throw\", error, resolve, reject);\n });\n }\n }\n\n var previousPromise;\n\n function enqueue(method, arg) {\n function callInvokeWithMethodAndArg() {\n return new PromiseImpl(function(resolve, reject) {\n invoke(method, arg, resolve, reject);\n });\n }\n\n return previousPromise =\n // If enqueue has been called before, then we want to wait until\n // all previous Promises have been resolved before calling invoke,\n // so that results are always delivered in the correct order. If\n // enqueue has not been called before, then it is important to\n // call invoke immediately, without waiting on a callback to fire,\n // so that the async generator function has the opportunity to do\n // any necessary setup in a predictable way. This predictability\n // is why the Promise constructor synchronously invokes its\n // executor callback, and why async functions synchronously\n // execute code before the first await. Since we implement simple\n // async functions in terms of async generators, it is especially\n // important to get this right, even though it requires care.\n previousPromise ? previousPromise.then(\n callInvokeWithMethodAndArg,\n // Avoid propagating failures to Promises returned by later\n // invocations of the iterator.\n callInvokeWithMethodAndArg\n ) : callInvokeWithMethodAndArg();\n }\n\n // Define the unified helper method that is used to implement .next,\n // .throw, and .return (see defineIteratorMethods).\n this._invoke = enqueue;\n }\n\n defineIteratorMethods(AsyncIterator.prototype);\n AsyncIterator.prototype[asyncIteratorSymbol] = function () {\n return this;\n };\n exports.AsyncIterator = AsyncIterator;\n\n // Note that simple async functions are implemented on top of\n // AsyncIterator objects; they just return a Promise for the value of\n // the final result produced by the iterator.\n exports.async = function(innerFn, outerFn, self, tryLocsList, PromiseImpl) {\n if (PromiseImpl === void 0) PromiseImpl = Promise;\n\n var iter = new AsyncIterator(\n wrap(innerFn, outerFn, self, tryLocsList),\n PromiseImpl\n );\n\n return exports.isGeneratorFunction(outerFn)\n ? iter // If outerFn is a generator, return the full iterator.\n : iter.next().then(function(result) {\n return result.done ? result.value : iter.next();\n });\n };\n\n function makeInvokeMethod(innerFn, self, context) {\n var state = GenStateSuspendedStart;\n\n return function invoke(method, arg) {\n if (state === GenStateExecuting) {\n throw new Error(\"Generator is already running\");\n }\n\n if (state === GenStateCompleted) {\n if (method === \"throw\") {\n throw arg;\n }\n\n // Be forgiving, per 25.3.3.3.3 of the spec:\n // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume\n return doneResult();\n }\n\n context.method = method;\n context.arg = arg;\n\n while (true) {\n var delegate = context.delegate;\n if (delegate) {\n var delegateResult = maybeInvokeDelegate(delegate, context);\n if (delegateResult) {\n if (delegateResult === ContinueSentinel) continue;\n return delegateResult;\n }\n }\n\n if (context.method === \"next\") {\n // Setting context._sent for legacy support of Babel's\n // function.sent implementation.\n context.sent = context._sent = context.arg;\n\n } else if (context.method === \"throw\") {\n if (state === GenStateSuspendedStart) {\n state = GenStateCompleted;\n throw context.arg;\n }\n\n context.dispatchException(context.arg);\n\n } else if (context.method === \"return\") {\n context.abrupt(\"return\", context.arg);\n }\n\n state = GenStateExecuting;\n\n var record = tryCatch(innerFn, self, context);\n if (record.type === \"normal\") {\n // If an exception is thrown from innerFn, we leave state ===\n // GenStateExecuting and loop back for another invocation.\n state = context.done\n ? GenStateCompleted\n : GenStateSuspendedYield;\n\n if (record.arg === ContinueSentinel) {\n continue;\n }\n\n return {\n value: record.arg,\n done: context.done\n };\n\n } else if (record.type === \"throw\") {\n state = GenStateCompleted;\n // Dispatch the exception by looping back around to the\n // context.dispatchException(context.arg) call above.\n context.method = \"throw\";\n context.arg = record.arg;\n }\n }\n };\n }\n\n // Call delegate.iterator[context.method](context.arg) and handle the\n // result, either by returning a { value, done } result from the\n // delegate iterator, or by modifying context.method and context.arg,\n // setting context.delegate to null, and returning the ContinueSentinel.\n function maybeInvokeDelegate(delegate, context) {\n var method = delegate.iterator[context.method];\n if (method === undefined) {\n // A .throw or .return when the delegate iterator has no .throw\n // method always terminates the yield* loop.\n context.delegate = null;\n\n if (context.method === \"throw\") {\n // Note: [\"return\"] must be used for ES3 parsing compatibility.\n if (delegate.iterator[\"return\"]) {\n // If the delegate iterator has a return method, give it a\n // chance to clean up.\n context.method = \"return\";\n context.arg = undefined;\n maybeInvokeDelegate(delegate, context);\n\n if (context.method === \"throw\") {\n // If maybeInvokeDelegate(context) changed context.method from\n // \"return\" to \"throw\", let that override the TypeError below.\n return ContinueSentinel;\n }\n }\n\n context.method = \"throw\";\n context.arg = new TypeError(\n \"The iterator does not provide a 'throw' method\");\n }\n\n return ContinueSentinel;\n }\n\n var record = tryCatch(method, delegate.iterator, context.arg);\n\n if (record.type === \"throw\") {\n context.method = \"throw\";\n context.arg = record.arg;\n context.delegate = null;\n return ContinueSentinel;\n }\n\n var info = record.arg;\n\n if (! info) {\n context.method = \"throw\";\n context.arg = new TypeError(\"iterator result is not an object\");\n context.delegate = null;\n return ContinueSentinel;\n }\n\n if (info.done) {\n // Assign the result of the finished delegate to the temporary\n // variable specified by delegate.resultName (see delegateYield).\n context[delegate.resultName] = info.value;\n\n // Resume execution at the desired location (see delegateYield).\n context.next = delegate.nextLoc;\n\n // If context.method was \"throw\" but the delegate handled the\n // exception, let the outer generator proceed normally. If\n // context.method was \"next\", forget context.arg since it has been\n // \"consumed\" by the delegate iterator. If context.method was\n // \"return\", allow the original .return call to continue in the\n // outer generator.\n if (context.method !== \"return\") {\n context.method = \"next\";\n context.arg = undefined;\n }\n\n } else {\n // Re-yield the result returned by the delegate method.\n return info;\n }\n\n // The delegate iterator is finished, so forget it and continue with\n // the outer generator.\n context.delegate = null;\n return ContinueSentinel;\n }\n\n // Define Generator.prototype.{next,throw,return} in terms of the\n // unified ._invoke helper method.\n defineIteratorMethods(Gp);\n\n define(Gp, toStringTagSymbol, \"Generator\");\n\n // A Generator should always return itself as the iterator object when the\n // @@iterator function is called on it. Some browsers' implementations of the\n // iterator prototype chain incorrectly implement this, causing the Generator\n // object to not be returned from this call. This ensures that doesn't happen.\n // See https://github.com/facebook/regenerator/issues/274 for more details.\n Gp[iteratorSymbol] = function() {\n return this;\n };\n\n Gp.toString = function() {\n return \"[object Generator]\";\n };\n\n function pushTryEntry(locs) {\n var entry = { tryLoc: locs[0] };\n\n if (1 in locs) {\n entry.catchLoc = locs[1];\n }\n\n if (2 in locs) {\n entry.finallyLoc = locs[2];\n entry.afterLoc = locs[3];\n }\n\n this.tryEntries.push(entry);\n }\n\n function resetTryEntry(entry) {\n var record = entry.completion || {};\n record.type = \"normal\";\n delete record.arg;\n entry.completion = record;\n }\n\n function Context(tryLocsList) {\n // The root entry object (effectively a try statement without a catch\n // or a finally block) gives us a place to store values thrown from\n // locations where there is no enclosing try statement.\n this.tryEntries = [{ tryLoc: \"root\" }];\n tryLocsList.forEach(pushTryEntry, this);\n this.reset(true);\n }\n\n exports.keys = function(object) {\n var keys = [];\n for (var key in object) {\n keys.push(key);\n }\n keys.reverse();\n\n // Rather than returning an object with a next method, we keep\n // things simple and return the next function itself.\n return function next() {\n while (keys.length) {\n var key = keys.pop();\n if (key in object) {\n next.value = key;\n next.done = false;\n return next;\n }\n }\n\n // To avoid creating an additional object, we just hang the .value\n // and .done properties off the next function object itself. This\n // also ensures that the minifier will not anonymize the function.\n next.done = true;\n return next;\n };\n };\n\n function values(iterable) {\n if (iterable) {\n var iteratorMethod = iterable[iteratorSymbol];\n if (iteratorMethod) {\n return iteratorMethod.call(iterable);\n }\n\n if (typeof iterable.next === \"function\") {\n return iterable;\n }\n\n if (!isNaN(iterable.length)) {\n var i = -1, next = function next() {\n while (++i < iterable.length) {\n if (hasOwn.call(iterable, i)) {\n next.value = iterable[i];\n next.done = false;\n return next;\n }\n }\n\n next.value = undefined;\n next.done = true;\n\n return next;\n };\n\n return next.next = next;\n }\n }\n\n // Return an iterator with no values.\n return { next: doneResult };\n }\n exports.values = values;\n\n function doneResult() {\n return { value: undefined, done: true };\n }\n\n Context.prototype = {\n constructor: Context,\n\n reset: function(skipTempReset) {\n this.prev = 0;\n this.next = 0;\n // Resetting context._sent for legacy support of Babel's\n // function.sent implementation.\n this.sent = this._sent = undefined;\n this.done = false;\n this.delegate = null;\n\n this.method = \"next\";\n this.arg = undefined;\n\n this.tryEntries.forEach(resetTryEntry);\n\n if (!skipTempReset) {\n for (var name in this) {\n // Not sure about the optimal order of these conditions:\n if (name.charAt(0) === \"t\" &&\n hasOwn.call(this, name) &&\n !isNaN(+name.slice(1))) {\n this[name] = undefined;\n }\n }\n }\n },\n\n stop: function() {\n this.done = true;\n\n var rootEntry = this.tryEntries[0];\n var rootRecord = rootEntry.completion;\n if (rootRecord.type === \"throw\") {\n throw rootRecord.arg;\n }\n\n return this.rval;\n },\n\n dispatchException: function(exception) {\n if (this.done) {\n throw exception;\n }\n\n var context = this;\n function handle(loc, caught) {\n record.type = \"throw\";\n record.arg = exception;\n context.next = loc;\n\n if (caught) {\n // If the dispatched exception was caught by a catch block,\n // then let that catch block handle the exception normally.\n context.method = \"next\";\n context.arg = undefined;\n }\n\n return !! caught;\n }\n\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n var record = entry.completion;\n\n if (entry.tryLoc === \"root\") {\n // Exception thrown outside of any try block that could handle\n // it, so set the completion value of the entire function to\n // throw the exception.\n return handle(\"end\");\n }\n\n if (entry.tryLoc <= this.prev) {\n var hasCatch = hasOwn.call(entry, \"catchLoc\");\n var hasFinally = hasOwn.call(entry, \"finallyLoc\");\n\n if (hasCatch && hasFinally) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n } else if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else if (hasCatch) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n }\n\n } else if (hasFinally) {\n if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else {\n throw new Error(\"try statement without catch or finally\");\n }\n }\n }\n },\n\n abrupt: function(type, arg) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc <= this.prev &&\n hasOwn.call(entry, \"finallyLoc\") &&\n this.prev < entry.finallyLoc) {\n var finallyEntry = entry;\n break;\n }\n }\n\n if (finallyEntry &&\n (type === \"break\" ||\n type === \"continue\") &&\n finallyEntry.tryLoc <= arg &&\n arg <= finallyEntry.finallyLoc) {\n // Ignore the finally entry if control is not jumping to a\n // location outside the try/catch block.\n finallyEntry = null;\n }\n\n var record = finallyEntry ? finallyEntry.completion : {};\n record.type = type;\n record.arg = arg;\n\n if (finallyEntry) {\n this.method = \"next\";\n this.next = finallyEntry.finallyLoc;\n return ContinueSentinel;\n }\n\n return this.complete(record);\n },\n\n complete: function(record, afterLoc) {\n if (record.type === \"throw\") {\n throw record.arg;\n }\n\n if (record.type === \"break\" ||\n record.type === \"continue\") {\n this.next = record.arg;\n } else if (record.type === \"return\") {\n this.rval = this.arg = record.arg;\n this.method = \"return\";\n this.next = \"end\";\n } else if (record.type === \"normal\" && afterLoc) {\n this.next = afterLoc;\n }\n\n return ContinueSentinel;\n },\n\n finish: function(finallyLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.finallyLoc === finallyLoc) {\n this.complete(entry.completion, entry.afterLoc);\n resetTryEntry(entry);\n return ContinueSentinel;\n }\n }\n },\n\n \"catch\": function(tryLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc === tryLoc) {\n var record = entry.completion;\n if (record.type === \"throw\") {\n var thrown = record.arg;\n resetTryEntry(entry);\n }\n return thrown;\n }\n }\n\n // The context.catch method must only be called with a location\n // argument that corresponds to a known catch block.\n throw new Error(\"illegal catch attempt\");\n },\n\n delegateYield: function(iterable, resultName, nextLoc) {\n this.delegate = {\n iterator: values(iterable),\n resultName: resultName,\n nextLoc: nextLoc\n };\n\n if (this.method === \"next\") {\n // Deliberately forget the last sent value so that we don't\n // accidentally pass it on to the delegate.\n this.arg = undefined;\n }\n\n return ContinueSentinel;\n }\n };\n\n // Regardless of whether this script is executing as a CommonJS module\n // or not, return the runtime object so that we can declare the variable\n // regeneratorRuntime in the outer scope, which allows this module to be\n // injected easily by `bin/regenerator --include-runtime script.js`.\n return exports;\n\n}(\n // If this script is executing as a CommonJS module, use module.exports\n // as the regeneratorRuntime namespace. Otherwise create a new empty\n // object. Either way, the resulting object will be used to initialize\n // the regeneratorRuntime variable at the top of this file.\n typeof module === \"object\" ? module.exports : {}\n));\n\ntry {\n regeneratorRuntime = runtime;\n} catch (accidentalStrictMode) {\n // This module should not be running in strict mode, so the above\n // assignment should always work unless something is misconfigured. Just\n // in case runtime.js accidentally runs in strict mode, we can escape\n // strict mode using a global Function call. This could conceivably fail\n // if a Content Security Policy forbids using Function, but in that case\n // the proper solution is to fix the accidental strict mode problem. If\n // you've misconfigured your bundler to force strict mode and applied a\n // CSP to forbid Function, and you're not willing to fix either of those\n // problems, please detail your unique predicament in a GitHub issue.\n Function(\"r\", \"regeneratorRuntime = r\")(runtime);\n}\n","module.exports = require(\"regenerator-runtime\");\n","function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {\n try {\n var info = gen[key](arg);\n var value = info.value;\n } catch (error) {\n reject(error);\n return;\n }\n\n if (info.done) {\n resolve(value);\n } else {\n Promise.resolve(value).then(_next, _throw);\n }\n}\n\nfunction _asyncToGenerator(fn) {\n return function () {\n var self = this,\n args = arguments;\n return new Promise(function (resolve, reject) {\n var gen = fn.apply(self, args);\n\n function _next(value) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"next\", value);\n }\n\n function _throw(err) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"throw\", err);\n }\n\n _next(undefined);\n });\n };\n}\n\nmodule.exports = _asyncToGenerator;","function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}\n\nmodule.exports = _classCallCheck;","function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\n\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}\n\nmodule.exports = _createClass;","export default class FetchService {\r\n constructor() {\r\n\r\n }\r\n\r\n async performGetHttpRequest(fetchLink, headers, query=null) {\r\n if(!fetchLink || !headers) {\r\n throw new Error(\"One or more GET request parameters was not passed.\");\r\n }\r\n try {\r\n const rawResponse = await fetch(fetchLink, {\r\n method: \"GET\",\r\n headers: headers,\r\n query: (query != null) ? query : \"\"\r\n });\r\n const content = await rawResponse.json();\r\n return content;\r\n }\r\n catch(err) {\r\n console.error(`Error at fetch GET: ${err}`);\r\n throw err;\r\n }\r\n }\r\n\r\n async performPostHttpRequest(fetchLink, headers, body) {\r\n if(!fetchLink || !headers || !body) {\r\n throw new Error(\"One or more POST request parameters was not passed.\");\r\n }\r\n try {\r\n const rawResponse = await fetch(fetchLink, {\r\n method: \"POST\",\r\n headers: headers,\r\n body: JSON.stringify(body)\r\n });\r\n const content = await rawResponse.json();\r\n return content;\r\n }\r\n catch(err) {\r\n console.error(`Error at fetch POST: ${err}`);\r\n throw err;\r\n }\r\n }\r\n\r\n async performPutHttpRequest(fetchLink, headers, body) {\r\n if(!fetchLink || !headers || !body) {\r\n throw new Error(\"One or more POST request parameters was not passed.\");\r\n }\r\n try {\r\n const rawResponse = await fetch(fetchLink, {\r\n method: \"PUT\",\r\n headers: headers,\r\n body: JSON.stringify(body)\r\n });\r\n const content = await rawResponse.json();\r\n return content;\r\n }\r\n catch(err) {\r\n console.error(`Error at fetch PUT: ${err}`);\r\n throw err;\r\n }\r\n }\r\n}","import FetchService from './service/FetchService';\r\n\r\n/*-- Objects --*/\r\nconst fetchService = new FetchService();\r\n/*-- /Objects --*/\r\n\r\n/*--Functions--*/\r\nasync function submitForm(e, form) {\r\n // 1. Prevent reloading page\r\n e.preventDefault();\r\n // 2. Submit the form\r\n // 2.1 User Interaction\r\n const btnSubmit = document.getElementById('btnSubmit');\r\n btnSubmit.disabled = true;\r\n setTimeout(() => btnSubmit.disabled = false, 2000);\r\n // 2.2 Build JSON body\r\n const jsonFormData = buildJsonFormData(form);\r\n // 2.3 Build Headers\r\n const headers = buildHeaders();\r\n // 2.4 Request & Response\r\n const response = await fetchService.performPostHttpRequest(`https://jsonplaceholder.typicode.com/posts`, headers, jsonFormData); // Uses JSON Placeholder\r\n console.log(response);\r\n // 2.5 Inform user of result\r\n if(response)\r\n window.location = `/success.html?FirstName=${response.FirstName}&LastName=${response.LastName}&Email=${response.Email}&id=${response.id}`;\r\n else\r\n alert(`An error occured.`);\r\n}\r\n\r\nfunction buildHeaders(authorization = null) {\r\n const headers = {\r\n \"Content-Type\": \"application/json\",\r\n \"Authorization\": (authorization) ? authorization : \"Bearer TOKEN_MISSING\"\r\n };\r\n return headers;\r\n}\r\n\r\nfunction buildJsonFormData(form) {\r\n const jsonFormData = { };\r\n for(const pair of new FormData(form)) {\r\n jsonFormData[pair[0]] = pair[1];\r\n }\r\n return jsonFormData;\r\n}\r\n/*--/Functions--*/\r\n\r\n/*--Event Listeners--*/\r\nconst sampleForm = document.querySelector(\"#sampleForm\");\r\nif(sampleForm) {\r\n sampleForm.addEventListener(\"submit\", function(e) {\r\n submitForm(e, this);\r\n });\r\n}\r\n/*--/Event Listeners--*/\r\n"]} -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | Form to API

Sample Form to JSON API

-------------------------------------------------------------------------------- /dist/styles.c6edcaf7.css: -------------------------------------------------------------------------------- 1 | body{display:flex;min-height:98vh;align-items:center;background-color:#f8f9fa}.container{padding:1rem 2.5rem 1.5rem;margin:auto}.card{animation:fadeIn .9s ease-in-out 0s 1;box-shadow:0 4px 8px 0 rgba(0,0,0,.2);border-radius:5px;transition:.3s}.card-color{background:#ebebeb;background:linear-gradient(90deg,#fff,#fcfcfc 42%,#fff)}.card:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,.2)}.form-row{margin-top:1rem!important;margin-bottom:1rem!important;padding:.5rem}.form-row label{display:block}.input-text{font-weight:500;background-color:#f0f0f0;padding:.6rem .3rem .6rem .6rem;border-width:0;border-radius:.3rem;-webkit-appearance:none;outline:none}.input-text-block{display:block}.input-text:focus{border-color:1px solid #444}.input-text:disabled{opacity:.7;cursor:auto}.btn-edit,.btn-submit{padding:.7rem;text-decoration:none;color:#fff;border:none;border-radius:.8rem;font-weight:700}.btn-submit{background-color:#000;width:100%}.btn-edit{background-color:transparent}path{fill:#aaa}button:hover{opacity:.9}button:focus{opacity:1}button:focus,button:hover{cursor:pointer}button:disabled{opacity:.7;cursor:not-allowed}.d-flex{display:flex}.justify-content-end{justify-content:end;justify-content:flex-end}.m-2{margin:2rem}.my-1{margin-top:1rem;margin-bottom:1rem}.mx-auto{margin-right:auto;margin-left:auto}.w-100{width:100%}.text-center{text-align:center} 2 | /*# sourceMappingURL=/styles.c6edcaf7.css.map */ -------------------------------------------------------------------------------- /dist/styles.c6edcaf7.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["styles.css"],"names":[],"mappings":"AACA,KACI,YAAa,CACb,eAAgB,CAChB,kBAAmB,CACnB,wBACF,CAGA,WACI,0BAAkC,CAClC,WACJ,CAEA,MACI,qCAAuC,CACvC,qCAAuC,CACvC,iBAAkB,CAClB,cACJ,CACA,YACI,kBAA4B,CAC5B,uDACJ,CACA,YACI,sCACJ,CAGA,UACI,yBAA2B,CAC3B,4BAA8B,CAC9B,aACJ,CACA,gBACI,aACJ,CAIA,YACI,eAAgB,CAChB,wBAAyB,CACzB,+BAAoC,CACpC,cAAe,CACf,mBAAqB,CACrB,uBAAwB,CACxB,YACJ,CACA,kBACI,aACJ,CACA,kBACI,2BACJ,CACA,qBACI,UAAY,CACZ,WACJ,CAGA,sBACI,aAAe,CACf,oBAAqB,CACrB,UAAW,CACX,WAAY,CACZ,mBAAqB,CACrB,eACJ,CACA,YACE,qBAAsB,CACtB,UACF,CACA,UACE,4BACF,CACA,KACE,SACF,CACA,aACI,UACJ,CACA,aACI,SACJ,CACA,0BACE,cACF,CACA,gBACE,UAAY,CACZ,kBACF,CAIA,QACE,YACF,CACA,qBACE,mBAAoB,CACpB,wBAEF,CACA,KACI,WACJ,CACA,MACE,eAAgB,CAChB,kBACF,CACA,SACE,iBAAkB,CAClB,gBACF,CACA,OACE,UACF,CACA,aACI,iBACJ","file":"styles.c6edcaf7.css","sourceRoot":"..\\src","sourcesContent":["/*-- body --*/\r\nbody {\r\n display: flex;\r\n min-height: 98vh;\r\n align-items: center;\r\n background-color: #f8f9fa;\r\n }\r\n /*-- /body --*/\r\n /*-- Container & Card --*/\r\n .container {\r\n padding: 1rem 2.5rem 1.5rem 2.5rem;\r\n margin: auto;\r\n }\r\n \r\n .card {\r\n animation: 0.9s ease-in-out 0s 1 fadeIn;\r\n box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);\r\n border-radius: 5px;\r\n transition: 0.3s;\r\n }\r\n .card-color {\r\n background: rgb(235,235,235);\r\n background: linear-gradient(90deg, rgba(255,255,255,1) 0%, rgba(252,252,252,1) 42%, rgba(255,255,255,1) 100%);\r\n }\r\n .card:hover {\r\n box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);\r\n }\r\n /*-- /Container & Card --*/\r\n /*-- form --*/\r\n .form-row {\r\n margin-top: 1rem !important;\r\n margin-bottom: 1rem !important;\r\n padding: 0.5rem;\r\n }\r\n .form-row label {\r\n display: block;\r\n }\r\n /*-- /form --*/\r\n \r\n /*-- TextInput --*/\r\n .input-text {\r\n font-weight: 500;\r\n background-color: #f0f0f0;\r\n padding: 0.6rem 0.3rem 0.6rem 0.6rem;\r\n border-width: 0;\r\n border-radius: 0.3rem;\r\n -webkit-appearance: none;\r\n outline: none;\r\n }\r\n .input-text-block {\r\n display: block;\r\n }\r\n .input-text:focus {\r\n border-color: 1px solid #444;\r\n }\r\n .input-text:disabled {\r\n opacity: 0.7;\r\n cursor: auto;\r\n }\r\n /*-- /TextInput --*/\r\n /*-- Button --*/\r\n .btn-submit, .btn-edit {\r\n padding: 0.7rem;\r\n text-decoration: none;\r\n color: #FFF;\r\n border: none;\r\n border-radius: 0.8rem;\r\n font-weight: bold;\r\n }\r\n .btn-submit {\r\n background-color: #000;\r\n width: 100%;\r\n }\r\n .btn-edit {\r\n background-color: transparent;\r\n }\r\n path {\r\n fill: #aaa;\r\n }\r\n button:hover {\r\n opacity: 0.9;\r\n }\r\n button:focus {\r\n opacity: 1; \r\n }\r\n button:hover, button:focus {\r\n cursor: pointer;\r\n }\r\n button:disabled {\r\n opacity: 0.7;\r\n cursor: not-allowed;\r\n }\r\n /*-- /Button --*/\r\n \r\n /*-- Utils --*/\r\n .d-flex {\r\n display: flex;\r\n }\r\n .justify-content-end {\r\n justify-content: end; \r\n justify-content: flex-end;\r\n \r\n }\r\n .m-2 {\r\n margin: 2rem;\r\n }\r\n .my-1 {\r\n margin-top: 1rem;\r\n margin-bottom: 1rem;\r\n }\r\n .mx-auto {\r\n margin-right: auto;\r\n margin-left: auto;\r\n }\r\n .w-100 {\r\n width: 100%;\r\n }\r\n .text-center {\r\n text-align: center;\r\n }\r\n /*-- /Utils --*/"]} -------------------------------------------------------------------------------- /dist/success.html: -------------------------------------------------------------------------------- 1 | Form to API

Success

-------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "submittingformstoapis", 3 | "version": "1.0.0", 4 | "description": "demo to submit html forms to APIs", 5 | "main": "index.html", 6 | "scripts": { 7 | "dev": "npm run clean && parcel src/index.html --out-dir dev", 8 | "build": "parcel build src/*.html --public-url ./", 9 | "clean": "rimraf ./dev && rimraf -rf ./.cache" 10 | }, 11 | "keywords": [ 12 | "form", 13 | "html", 14 | "json", 15 | "api", 16 | "fetch", 17 | "post", 18 | "request" 19 | ], 20 | "author": "Amjad Abujamous", 21 | "license": "ISC", 22 | "dependencies": { 23 | "@babel/cli": "^7.11.6", 24 | "@babel/core": "^7.11.6", 25 | "@babel/plugin-transform-runtime": "^7.11.5", 26 | "@babel/preset-env": "^7.11.5", 27 | "parcel-bundler": "^1.12.4", 28 | "parcel-plugin-html-partials": "0.0.6", 29 | "save": "^2.4.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/css/styles.css: -------------------------------------------------------------------------------- 1 | /*-- body --*/ 2 | body { 3 | display: flex; 4 | min-height: 98vh; 5 | align-items: center; 6 | background-color: #f8f9fa; 7 | } 8 | /*-- /body --*/ 9 | /*-- Container & Card --*/ 10 | .container { 11 | padding: 1rem 2.5rem 1.5rem 2.5rem; 12 | margin: auto; 13 | } 14 | 15 | .card { 16 | animation: 0.9s ease-in-out 0s 1 fadeIn; 17 | box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); 18 | border-radius: 5px; 19 | transition: 0.3s; 20 | } 21 | .card-color { 22 | background: rgb(235,235,235); 23 | background: linear-gradient(90deg, rgba(255,255,255,1) 0%, rgba(252,252,252,1) 42%, rgba(255,255,255,1) 100%); 24 | } 25 | .card:hover { 26 | box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2); 27 | } 28 | /*-- /Container & Card --*/ 29 | /*-- form --*/ 30 | .form-row { 31 | margin-top: 1rem !important; 32 | margin-bottom: 1rem !important; 33 | padding: 0.5rem; 34 | } 35 | .form-row label { 36 | display: block; 37 | } 38 | /*-- /form --*/ 39 | 40 | /*-- TextInput --*/ 41 | .input-text { 42 | font-weight: 500; 43 | background-color: #f0f0f0; 44 | padding: 0.6rem 0.3rem 0.6rem 0.6rem; 45 | border-width: 0; 46 | border-radius: 0.3rem; 47 | -webkit-appearance: none; 48 | outline: none; 49 | } 50 | .input-text-block { 51 | display: block; 52 | } 53 | .input-text:focus { 54 | border-color: 1px solid #444; 55 | } 56 | .input-text:disabled { 57 | opacity: 0.7; 58 | cursor: auto; 59 | } 60 | /*-- /TextInput --*/ 61 | /*-- Button --*/ 62 | .btn-submit, .btn-edit { 63 | padding: 0.7rem; 64 | text-decoration: none; 65 | color: #FFF; 66 | border: none; 67 | border-radius: 0.8rem; 68 | font-weight: bold; 69 | } 70 | .btn-submit { 71 | background-color: #000; 72 | width: 100%; 73 | } 74 | .btn-edit { 75 | background-color: transparent; 76 | } 77 | path { 78 | fill: #aaa; 79 | } 80 | button:hover { 81 | opacity: 0.9; 82 | } 83 | button:focus { 84 | opacity: 1; 85 | } 86 | button:hover, button:focus { 87 | cursor: pointer; 88 | } 89 | button:disabled { 90 | opacity: 0.7; 91 | cursor: not-allowed; 92 | } 93 | /*-- /Button --*/ 94 | 95 | /*-- Utils --*/ 96 | .d-flex { 97 | display: flex; 98 | } 99 | .justify-content-end { 100 | justify-content: end; 101 | justify-content: flex-end; 102 | 103 | } 104 | .m-2 { 105 | margin: 2rem; 106 | } 107 | .my-1 { 108 | margin-top: 1rem; 109 | margin-bottom: 1rem; 110 | } 111 | .mx-auto { 112 | margin-right: auto; 113 | margin-left: auto; 114 | } 115 | .w-100 { 116 | width: 100%; 117 | } 118 | .text-center { 119 | text-align: center; 120 | } 121 | /*-- /Utils --*/ -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Form to API 8 | 9 | 10 |
11 |
12 |

Sample Form to JSON API

13 |
14 | 15 | 16 |
17 |
18 | 19 | 20 |
21 |
22 | 23 | 24 |
25 |
26 | 29 |
30 |
31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /src/js/app.js: -------------------------------------------------------------------------------- 1 | import FetchService from './service/FetchService.js'; 2 | 3 | /*-- Objects --*/ 4 | const fetchService = new FetchService(); 5 | /*-- /Objects --*/ 6 | 7 | /*--Functions--*/ 8 | async function submitForm(e, form) { 9 | // 1. Prevent reloading page 10 | e.preventDefault(); 11 | // 2. Submit the form 12 | // 2.1 User Interaction 13 | const btnSubmit = document.getElementById('btnSubmit'); 14 | btnSubmit.disabled = true; 15 | setTimeout(() => btnSubmit.disabled = false, 2000); 16 | // 2.2 Build JSON body 17 | const jsonFormData = buildJsonFormData(form); 18 | // 2.3 Build Headers 19 | const headers = buildHeaders(); 20 | // 2.4 Request & Response 21 | const response = await fetchService.performPostHttpRequest(`https://jsonplaceholder.typicode.com/posts`, headers, jsonFormData); // Uses JSON Placeholder 22 | console.log(response); 23 | // 2.5 Inform user of result 24 | if(response) 25 | window.location = `/success.html?FirstName=${response.FirstName}&LastName=${response.LastName}&Email=${response.Email}&id=${response.id}`; 26 | else 27 | alert(`An error occured.`); 28 | } 29 | 30 | function buildHeaders(authorization = null) { 31 | const headers = { 32 | "Content-Type": "application/json", 33 | "Authorization": (authorization) ? authorization : "Bearer TOKEN_MISSING" 34 | }; 35 | return headers; 36 | } 37 | 38 | function buildJsonFormData(form) { 39 | const jsonFormData = { }; 40 | for(const pair of new FormData(form)) { 41 | jsonFormData[pair[0]] = pair[1]; 42 | } 43 | return jsonFormData; 44 | } 45 | /*--/Functions--*/ 46 | 47 | /*--Event Listeners--*/ 48 | const sampleForm = document.querySelector("#sampleForm"); 49 | if(sampleForm) { 50 | sampleForm.addEventListener("submit", function(e) { 51 | submitForm(e, this); 52 | }); 53 | } 54 | /*--/Event Listeners--*/ 55 | -------------------------------------------------------------------------------- /src/js/service/FetchService.js: -------------------------------------------------------------------------------- 1 | export default class FetchService { 2 | constructor() { 3 | 4 | } 5 | 6 | async performGetHttpRequest(fetchLink, headers, query=null) { 7 | if(!fetchLink || !headers) { 8 | throw new Error("One or more GET request parameters was not passed."); 9 | } 10 | try { 11 | const rawResponse = await fetch(fetchLink, { 12 | method: "GET", 13 | headers: headers, 14 | query: (query != null) ? query : "" 15 | }); 16 | const content = await rawResponse.json(); 17 | return content; 18 | } 19 | catch(err) { 20 | console.error(`Error at fetch GET: ${err}`); 21 | throw err; 22 | } 23 | } 24 | 25 | async performPostHttpRequest(fetchLink, headers, body) { 26 | if(!fetchLink || !headers || !body) { 27 | throw new Error("One or more POST request parameters was not passed."); 28 | } 29 | try { 30 | const rawResponse = await fetch(fetchLink, { 31 | method: "POST", 32 | headers: headers, 33 | body: JSON.stringify(body) 34 | }); 35 | const content = await rawResponse.json(); 36 | return content; 37 | } 38 | catch(err) { 39 | console.error(`Error at fetch POST: ${err}`); 40 | throw err; 41 | } 42 | } 43 | 44 | async performPutHttpRequest(fetchLink, headers, body) { 45 | if(!fetchLink || !headers || !body) { 46 | throw new Error("One or more POST request parameters was not passed."); 47 | } 48 | try { 49 | const rawResponse = await fetch(fetchLink, { 50 | method: "PUT", 51 | headers: headers, 52 | body: JSON.stringify(body) 53 | }); 54 | const content = await rawResponse.json(); 55 | return content; 56 | } 57 | catch(err) { 58 | console.error(`Error at fetch PUT: ${err}`); 59 | throw err; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/success.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Form to API 8 | 9 | 10 |
11 |

Success

12 |
13 | Go Back 14 |
15 |
16 | 17 | 18 | --------------------------------------------------------------------------------