Package Exports
- ak-field-base
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (ak-field-base) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
FieldBase
This component contains all the common behaviour and styles for fields
FieldBase provides an Atlassian Design Guidelines compatible implementation for:
- Labels: spacing, margins, accessibility and click-to-focus functionality
- Fields: sizing, borders, colors, wrapping behaviour, hover/focus states
- Inline edit pattern: view switching, edit/confirm/cancel buttons, focus handling
- Validation: styles, waiting states (built in validation coming soon!)
- Keyboard navigation: view switching, confirm/cancel behaviour with associated focus styles
FieldBase's will work by themselves but are really meant to be extended into a full field component.
Try it out
Interact with a live demo of the ak-field-base component.
Installation
npm install ak-field-baseUsing the component
FieldBase makes no assumptions about libraries or frameworks and can be extended any way you like; Skatejs, React or even Vanilla JS.
Creating your views
FieldBase works using two 'views' for your component editmode and viewmode.
To set these up, simply pass them as children to your FieldBase with the appropriate slot attribute.
<ak-field-base label="My awesome field" id="myCustomField">
<div slot="viewmode">
<span id="viewModeValue">Your text here</span>
</div>
<div slot="editmode">
<input type="text" id="inputField" value="Your text here" />
</div>
</ak-field-base>Note: It is very important to pass in the label prop even if you are hiding it using the
hideLabel prop as the label is used to make your field accessible for screen readers.
At this point you will already have a component that can switch between views, handle keyboard navigation and set aside an appropriate amount of space.
However, this isn't particularly useful because our changes aren't saved!
Updating views
To keep our two views in sync, we'll need to set up some event handlers to tell us when a user is switching views.
The two events for this are exitViewingView and exitEditingView respectively.
We'll simply listen for the exitEditingView event and if a user clicked confirm, we'll update our viewmode.
If they click cancel we'll take their last value and put that back into the input field so that the next time they enter editmode it has the correct value.
// import the custom event from the FieldBase package
import { events } from 'ak-field-base';
const fieldBase = document.getElementById('myCustomField');
const inputField = document.getElementById('inputField');
const viewModeSpan = document.getElementById('viewModeValue');
// We'll need to keep track of the value of our field
let fieldValue = inputField.value;
// now set up our event listener
fieldBase.addEventListener(events.exitEditingView, (e) => {
// we can check if the change was caused by hitting cancel or not
if (e.detail.cancelButtonPressed) {
// we'll reset the value to the last one before the cancel
inputField.value = fieldValue;
} else {
// we'll update our state and reflect it into the viewmode
fieldValue = inputField.value;
viewModeSpan.innerHTML = fieldValue;
}
})Styling content
You'll almost definitely want to apply some styles to your views so that they blend in with the Atlassian Design Guidelines theme.
In our example above, you would want to:
- Remove default focus styles from the input
- Remove borders and background-color from the input
- Reflect the input's focus state onto fieldBase (so that we get the correct focus styles in editmode)
To fix the styles we can either set them through javascript/regular css or just use inline styles.
<ak-field-base label="My awesome field" id="myCustomField">
<div slot="viewmode">
<span id="viewModeValue">Your text here</span>
</div>
<div slot="editmode">
<input type="text" id="inputField" value="Your text here" style="background: transparent; border: 0; outline: 0; width: 100%;" />
</div>
</ak-field-base>inputField.style.background = 'transparent';
inputField.style.border = '0';
inputField.style.outline = 'none';
inputField.style.width = '100%';To fix the focus styling we can set up event listeners on the input that can set the focused prop on FieldBase.
inputField.addEventListener('focus', () => {
fieldBase.focused = true;
});
inputField.addEventListener('blur', () => {
fieldBase.focused = false;
});Validation
Performing validation is as easy listening for the exitEditingView event and responding appropriately.
If the validation can be performed client-side, simply check the value, if it is invalid cancel the event
and set the invalid prop on fieldBase.
fieldBase.addEventListener(events.exitEditingView, (e) => {
if (!e.detail.cancelButtonPressed) {
if (inputField.value.length % 2 !== 0) {
// error! the field only accepts strings that have an even number of characters!
e.preventDefault();
fieldBase.invalid = true;
}
}
});To perform async validation it is recommended that you use the waiting prop whilst you wait.
fieldBase.addEventListener(events.exitEditingView, (e) => {
if (!e.detail.cancelButtonPressed) {
// we'll cancel the event so that we don't go to viewmode yet
e.preventDefault();
fieldBase.waiting = true;
// now we'll call some long running validation function
validateValueOnServer(inputField.value).then(isValid => {
if (isValid) {
// the value was valid, remove the waiting, editing and invalid props
fieldBase.waiting = false;
fieldBase.editing = false;
fieldBase.invalid = false;
// and update our state
fieldValue = inputField.value;
} else {
// the value wasn't valid, we'll mark fieldBase as invalid and let the user handle that
fieldBase.waiting = false;
fieldBase.invalid = true;
}
});
}
})FieldBase
Kind: global class
Emits: exitViewingView, exitEditingView
Properties
- fieldBase.label :
string - fieldBase.editing :
boolean - fieldBase.focused :
boolean - fieldBase.hideLabel :
boolean - fieldBase.waiting :
boolean - fieldBase.invalid :
boolean
- fieldBase.label :
Events
new FieldBase()
Create instances of the component programmatically, or using markup.
HTML Example
<ak-field-base label="Email" />JS Example
import FieldBase from 'ak-field-base';
const field = new FieldBase();
field.label = 'Email';
document.body.appendChild(field);fieldBase.label : string
The label to be rendered above the form field.
This prop is still required, even if the hideLabel prop is set as the label is also used to make the field accessible for screen readers.
Kind: instance property of FieldBase
fieldBase.editing : boolean
Whether the editing mode or viewing mode should be shown.
Defaults to false.
Kind: instance property of FieldBase
HTML Example
<ak-field-base editing></ak-field-base>JS Example
field.editing = true;fieldBase.focused : boolean
Whether the field should show it's focus ring.
This would usually be controlled by a component extending FieldBase and setting this when needed.
Defaults to false.
Kind: instance property of FieldBase
HTML Example
<ak-field-base focused></ak-field-base>JS Example
field.focused = true;fieldBase.hideLabel : boolean
Whether the field should show a label above it.
If set to true no label will be shown and no space will be reserved for it.
Note: You must still provide a label for the component regardless of this prop. The label is also used to make the field accessible to screen readers.
Defaults to false.
Kind: instance property of FieldBase
HTML Example
<ak-field-base label="First Name" hideLabel></ak-field-base>JS Example
field.label = 'First Name';
field.hideLabel = true;fieldBase.waiting : boolean
Whether or not to display a loading spinner next to the field.
This is usually used when you need to do some sort of async validation. Note that whilst the editing spinner is visible a user will not be able to click the confirm or cancel buttons from edit mode.
The spinner is only shown when the editing prop is true and will be ignored otherwise.
Kind: instance property of FieldBase
HTML Example
<ak-field-base editing waiting></ak-field-base>JS Example
field.editing = true;
field.waiting = true;fieldBase.invalid : boolean
Whether or not a field should show a validation error.
This is shown to the user through a red border currently but will also include error messages in a future release.
This prop is ignored if editing is not set to true.
Kind: instance property of FieldBase
HTML Example
<ak-field-base editing invalid></ak-field-base>JS Example
field.invalid = true;"exitViewingView"
This event gets emitted when a field is about to switch away from it's viewmode view.
You might choose to use this event to update your editmode content to be in sync with your viewmode, fetch data for your editmode or even cancel the event to prevent the change completely.
Kind: event emitted by FieldBase
JS Example
import { events } from 'ak-field-base';
field.addEventListener(events.exitViewingView, (e) => {
// perform your tasks here
// e.preventDefault(); will prevent the switch
});"exitEditingView"
This event gets emitted when a field is about to switch away from it's editmode view.
Here you could choose to update your viewmode content to match the users input or reset the value
shown in the editmode if the user hit cancel for example.
You might also choose to perform validation of the users value, this might involve cancelling the event to prevent the switch.
You can check if the user clicked the cancel button through the e.detail.cancelButtonPressed
value.
Kind: event emitted by FieldBase
JS Example
import { events } from 'ak-field-base';
field.addEventListener(events.exitEditingView, (e) => {
if (e.detail.cancelButtonPressed) {
// the user hit cancel
} else {
// the user hit confirm: perform validation, update view mode, etc
// e.preventDefault(); will cancel the switch and keep us in editmode
}
});Support and feedback
We're here to help!
Let us know what you think of our components and docs, your feedback is really important for us.
Community support
Ask a question in our forum.
Check if someone has already asked the same question before.
Create a support ticket
Are you in trouble? Let us know!