diff --git a/09-form-generation.adoc b/09-form-generation.adoc new file mode 100644 index 0000000..660a39b --- /dev/null +++ b/09-form-generation.adoc @@ -0,0 +1,164 @@ +## drop in an introduction on form generation + +- maybe go back and do this last + += Form Generation + +Imagine you're building a shiny new web app which requires users to register an account with a profile that includes their mailing address. You're using https://stripe.com[Stripe] for payments, and because of that, you're forced to limit registrations to the https://stripe.com/global[countries supported by Stripe]. Looking at their list on launch day, you see that they support _34 Countries_: + +.Stripe's list of supported countries on day 1 of your product launch +image::images/form-generation-stripe-countries.png[] + +Taking note of that list, you build out your HTML form with a ` + + + + + + +---- + +Having done that, you let the product out into the world. Maybe you make a mental note to check back on Stripe's list of supported countries in 6 months - or you do one better and log a ticket in your project tracking system so that it doesn't get forgotten forever. Even with the best of intentions, if Stripe updates their supported country list down the line, you may miss it for some length of time. At best, that represents a lost opportunity to gain paying customers in a new geography. But what happens if Stripe _removes_ a country from their list? Suddenly you've got a potentially very broken experience on your hands. Crap. + +In a better world, this is exactly where form generation would start to save your butt. After some googling, you find that Stripe actually has https://stripe.com/docs/api/country_specs/object[an API endpoint] which you can use to grab a list of countries which they support. It contains all of the metadata you'll need to make decisions about which countries to include in your dropdown list! Suddenly you've got a solution on your hands which is much more maintainable: + +---- +// note: this is a simplified example, done with react, for illustration purposes + +const countries = await fetch('https://api.stripe.com/v1/country_specs'); + +const countrySelect = ( + +); + +// render a select box with a list of countries +return countrySelect; +---- + +This approach can also save you loads of time when it comes to standardizing your UI. There's a principle in software development called DRY (Don't Repeat Yourself), which can serve as an easy litmus for front-end developers. Though the work may not have been incredibly complex, there's quite a bit of repeated code in the first example above. It's easy enough to add another country to that list by creating a new ` +); + +const CountryList = ({ countries }) => ( + +); +---- + +---- +// country list implemented as checkboxes +const CountryEntry = ({ country }) => ( + + {country.displayName} + +); + +const CountryList = ({ countries }) => ( + {countries.forEach(country => ( + + )} +); +---- + +== JSON Schema + +In the chapter on Validation, we discussed how JSON Schema can be used to keep form validation in tune with your API's validation rules. From a usability standpoint, using JSON Schema for validation alone can represent a massive leap in progress compared to old-world application development. As JSON Schema can _also_ be used to generate your app's input forms. + +Using JSON Schema to generate forms takes a bit of work up front, but saves you loads of manual work and error-prone repetition when things change. Essentially, for each data type which your application uses, your software will have a _set interface element_ which will be _dynamically generated_ to prompt for, validate, accept, and edit the type of data which it represents. + +If that sounds great - it's because it absolutely is. Imagine being able to add a field to a form just by telling the form that the field exists! What's more, there's loads of great libraries which already exist to help front end developers with this. As with anything else, you'd do well to search GitHub, NPM, PyPI, RubyGems, CocoaPods, Swift Package manager, and so on for well-maintained and widly used libraries in your implementation of choice. + +(For the examples below, we'll use the https://react-jsonschema-form.readthedocs.io/en/latest/[`react-jsonschema-form`] library to illustrate how this might work for you). + +Using JSON Schema form generation tools typically looks something like this: an input form is generated (at least inj part) by feeding JSON Schema data into the form generator. It provides hooks of some sort for your application to catch when the user requests a CRUD action from the form, providing some feedback for clientside validation alongh the way: + +``` +import React from 'react'; +import Form from 'react-jsonschema-form'; + +const sampleSchema = { + title: "Business Settings", + type: "object", + required: ["title"], + properties: { + title: {type: "string", title: "Title", default: "A new task"}, + done: {type: "boolean", title: "Done?", default: false} + } +}; +``` + +=== TODO TODO TODO finish this code sample +- pull schema contract from _somewhere else_ to illustrate how this actually works + +This, as you can imagine, can save loads of effort when building forms in your applications. Most of the well-supported form libraries are flexible enough to work with anything you might throw at them. Many are also extensible, allowing you to generate form controls from the UI library that you or your team are using for a given project. + +**EXAMPLE: generating forms from a given UI Library** +- show how to generate components from several UI Libraries + +=== Validation + +=== **think about merging this with chapter 08 on validation** + +Along with the shape of data required for your forms, JSON Schema provides for input and form validation, too. For a given field, you can proid + +- explain how type checking works in JSON Schema +- give a few examples of checking input validation: + - asynchronously + - on form submission + - waititng for response from API + +=== Resliance to API changes + +- this all is super duper awesome because when the API upstream from your project changes, you don't need to lose sweat as long as you're checking for updated JSON Schema definitions. +- how/when to cache this +- how to prepare for API updates +- example: how to read docs for important API changes (maybe talk about semver a bit?) +- APIs can change, this can help, we'll talk more about that in a later chapter + +=== Advising designers and front-end developers on how to use JSON Schema + +- talk a bit about Atomic Design as it applies to form generation +- storybook storybook storybook: + - 3rd party integrations - look for JSON Schema in docs for external APIs where you can generate interface for [their service]. If all else fails, talk to API developers about what you need! +- Set dev teams off on designing and building out form controls that are consistent with design guidelines before getting too deep on any specific form +- Give a few examples on how to display form validation errors: inline with fields given enough context, on top of a form if it isn't too large, near submit/cancel as a summary with invalid fields highlighted + +- other examples: https://json-schema.org/implementations.html#web-ui-generation + +Give some great exmaples of brand guidelines / front-end guidelines on what a date/text/toggle field looks like, point to changelogs to track updates + +=== Heavily customized UI Elements + +- there are some cases where you need to override the default: a type may say "array of strings", but really be asking for a selection of 1/many country names, or something like that + +=== When _not_ to do this +- sometimes json schema just doesn't fit. talk about how to detect and deal with that, and how to recognize scenarios where this makes sense +- \ No newline at end of file diff --git a/XX-form-generation.adoc b/XX-form-generation.adoc deleted file mode 100644 index 65141f0..0000000 --- a/XX-form-generation.adoc +++ /dev/null @@ -1,5 +0,0 @@ - -Users could only register in USA so the “Country” field was omitted on addresses, but now you sell globally and the country field is required on the API. The users cannot even enter the field because but users of the old the application cannot buy anything. -https://github.com/json-schema-form/json-schema-form-core -http://schemaform.io/ -https://mozilla-services.github.io/react-jsonschema-form/ \ No newline at end of file diff --git a/images/form-generation-stripe-countries.png b/images/form-generation-stripe-countries.png new file mode 100644 index 0000000..670729f Binary files /dev/null and b/images/form-generation-stripe-countries.png differ