Getting Started
This guide is an introduction on how to use the onlinq-collection
tags using
plain HTML forms to build input collections.
Building forms, and form collections in particular, is very precise and
repetitive which can be time-consuming to build and maintain. Using the
onlinq-collection
tags removes the burden of writing client-side code
allowing users to manipulate repetitive input data.
Note that this library does not provide any server-side validation for forms. The web components simply provide a shell around HTML inputs that helps to maintain a valid data structure when the user manipulates the collection.
Installation
If you're using a tool like Webpack to compile your assets, the easiest way to use the form collection components is by installing the package through NPM:
npm install @onlinq/form-collection
Importing the package in one of your JavaScript files will add the form collection elements to the HTML element registry on your page:
import '@onlinq/form-collection';
After including the JavaScript on your page, you can start using form
collections in your HTML-code with the onlinq-collection
tag.
Your First Collection
Who doesn't like fruit? It's sustainable, healthy and most of all tasty. The following examples will guide you through the steps to create a form where users can enter a list of their favorite fruits. Let's start with a basic form with just a few inputs to enter the data:
<form>
<label>What are your favorite fruits?</label>
<input type="text" name="fruits[0]" required="required" value="Apple">
<input type="text" name="fruits[1]" required="required" value="Banana">
<input type="text" name="fruits[2]" required="required" value="Orange">
<button type="submit">Submit</button>
</form>
View the example on CodePen.
The above example shows the most bare-bones implementation of a form collection possible. There are three inputs to enter a fruit, but there is no option to add or remove fruits from the list. It's also not possible order the fruits on the basis of deliciousness. To enable these features, we have to wrap the inputs in the form collection components.
First, the entire collection has to be wrapped in <onlinq-collection>
tags.
This is the container for the collection that keeps track of changes to
individual entries and propagates these changes to other entries in the
collection.
<onlinq-collection name="fruits">
<!-- the inputs here -->
</onlinq-collection>
Note that the web component needs either a name
or prefix
attribute corresponding to the prefix of the input's name
values. In our
example, the inputs are named fruits[x]
where x
is the input's index. The
prefix of the entire collection is in this case fruits
.
We're also going to configure the collection by setting a few
attributes to enable features, specifically allow-add
, allow-delete
and
allow-move
.
<onlinq-collection name="fruits" allow-add allow-delete allow-move>
Next, each input needs to wrapped in <onlinq-collection-entry>
tags for the
form collection to recognize each input as an individual entry.
<onlinq-collection-entry>
<input type="text" name="fruits[0]" required="required" value="Apple"/>
</onlinq-collection-entry>
For sake of completeness, each entry is going to get an collection-index
property which
value corresponds with the input's data index.
<onlinq-collection-entry collection-index="0">
If you check out this example on CodePen you'll notice that each entry now shows buttons beneath it to move the input up or down and to remove them from the list entirely.
At the end of the list a button might show up to add a new entry, but it isn't working yet. That's because for the collection to be able to generate new entries, we need to provide a template it can use to build the HTML for the new entry.
<template collection-prototype>
<input type="text" name="fruits[__name__]" required="required"/>
</template>
Add the template as a child to the onlinq-collection
element in the form.
The template has an attribute collection-prototype
to indicate that it's
used by the collection for new entries. Inside the template we replicate
an existing entry with one key difference, in the name
attribute of the input
the index is indicated by the string __name__
instead of a number. The
collection will replace this value by the next logical number in the collection
when it adds a new entry to the DOM.
That's it. We've incorporated the form collection components in our form so our users can enter as many delicious fruits as they like, in the order they prefer. The code should now look something like this:
<form>
<label>What are your favorite fruits?</label>
<onlinq-collection name="fruits" allow-add allow-delete allow-move>
<template collection-prototype>
<input type="text" name="fruits[__name__]" required="required"/>
</template>
<onlinq-collection-entry collection-index="0">
<input type="text" name="fruits[0]" required="required" value="Apple"/>
</onlinq-collection-entry>
<onlinq-collection-entry collection-index="1">
<input type="text" name="fruits[1]" required="required" value="Banana"/>
</onlinq-collection-entry>
<onlinq-collection-entry collection-index="2">
<input type="text" name="fruits[2]" required="required" value="Orange"/>
</onlinq-collection-entry>
</onlinq-collection>
<button type="submit">Submit</button>
</form>
View the example on CodePen.
Next Steps
Now that you know the basic workings of the form collection components, you can start customizing your collections by utilizing slots or extending the functionality with JavaScript.