Add ability to hydrate form from an http endpoint.
This commit is contained in:
@@ -111,7 +111,7 @@ export class Declaform extends HTMLElement {
|
||||
this._form = null;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
async connectedCallback() {
|
||||
const formSlot = this.shadowRoot?.querySelector('slot[name="form"]') as HTMLSlotElement;
|
||||
if (!formSlot) {
|
||||
throw new Error('[Declaform] Error: "form" slot is unassigned.')
|
||||
@@ -145,12 +145,11 @@ export class Declaform extends HTMLElement {
|
||||
for (const [name, inputs] of inputGroups.entries()) {
|
||||
this._fields.push(new Field(name, inputs))
|
||||
}
|
||||
/*
|
||||
|
||||
const src = this.getAttribute('src');
|
||||
if (src) {
|
||||
this.hydrateForm(src);
|
||||
this.hydrateFromEndpoint(src);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
get form() {
|
||||
@@ -197,6 +196,12 @@ export class Declaform extends HTMLElement {
|
||||
};
|
||||
populateFields(obj, '');
|
||||
}
|
||||
|
||||
private async hydrateFromEndpoint(endpoint: string): Promise<void> {
|
||||
const response = await fetch(endpoint);
|
||||
const obj = await response.json();
|
||||
this.hydrate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('decla-form', Declaform);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//import '../declaform';
|
||||
import { Declaform } from '../declaform';
|
||||
|
||||
const MOVIE_FORM = `
|
||||
const MOVIE_FORM_NO_SRC = `
|
||||
<decla-form id="form">
|
||||
<form slot="form">
|
||||
<div class="input-group">
|
||||
@@ -32,14 +31,49 @@ const MOVIE_FORM = `
|
||||
</decla-form>
|
||||
`;
|
||||
|
||||
const MOVIE_FORM_HTTP = `
|
||||
<decla-form id="form" src="get-movie/jaws">
|
||||
<form slot="form">
|
||||
<div class="input-group">
|
||||
<label for="name">Name</label>
|
||||
<input id="name" name="name" />
|
||||
</div>
|
||||
<select id="genre" name="genre">
|
||||
<option value="comedy">Comedy</option>
|
||||
<option value="horror">Horror</option>
|
||||
</select>
|
||||
<fieldset>
|
||||
<legend>Rating</legend>
|
||||
<div class="input-group">
|
||||
<label for="rating-type-user">Type</label>
|
||||
<input id="rating-type-user" name="rating.type" type="radio" value="user" />
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="rating-type-critic">Type</label>
|
||||
<input id="rating-type-critic" name="rating.type" type="radio" value="critic" />
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="rating-score">Score</label>
|
||||
<input id="rating-score" name="rating.score" type="number" />
|
||||
</div>
|
||||
</fieldset>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</decla-form>
|
||||
`;
|
||||
|
||||
describe('Declaform', () => {
|
||||
afterEach(() => {
|
||||
document.body.innerHTML = '';
|
||||
})
|
||||
|
||||
it('Should mount.', () => {
|
||||
document.body.innerHTML = MOVIE_FORM;
|
||||
document.body.innerHTML = MOVIE_FORM_NO_SRC;
|
||||
expect(document.getElementById('form')).toBeTruthy();
|
||||
})
|
||||
|
||||
it('.toObject() should serialize form into a JS object', () => {
|
||||
document.body.innerHTML = MOVIE_FORM;
|
||||
document.body.innerHTML = MOVIE_FORM_NO_SRC;
|
||||
const form = document.getElementById('form') as Declaform;
|
||||
setInputValue('name', 'Monty Python');
|
||||
setInputValue('genre', 'comedy');
|
||||
@@ -57,7 +91,7 @@ describe('Declaform', () => {
|
||||
});
|
||||
|
||||
it('.hydrate() should populate input fields from a JS object', () => {
|
||||
document.body.innerHTML = MOVIE_FORM;
|
||||
document.body.innerHTML = MOVIE_FORM_NO_SRC;
|
||||
const form = document.getElementById('form') as Declaform;
|
||||
form.hydrate({
|
||||
name: 'Jaws',
|
||||
@@ -71,7 +105,30 @@ describe('Declaform', () => {
|
||||
expect(getInputValue('genre')).toBe('horror')
|
||||
expect(getInputValue('rating-score')).toBe('5');
|
||||
expect(document.getElementById('rating-type-critic')?.hasAttribute('checked')).toBe(true)
|
||||
});
|
||||
|
||||
it('Supplying "src" attribute should hydrate form with the supplied endpoint.', async () => {
|
||||
global.fetch = jest.fn().mockResolvedValue({
|
||||
status: 200,
|
||||
ok: true,
|
||||
json: () => Promise.resolve({
|
||||
name: 'Jaws',
|
||||
genre: 'horror',
|
||||
rating: {
|
||||
score: 5,
|
||||
type: 'critic',
|
||||
}
|
||||
})
|
||||
})
|
||||
document.body.innerHTML = MOVIE_FORM_HTTP;
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 0))
|
||||
|
||||
expect(getInputValue('name')).toBe('Jaws')
|
||||
expect(getInputValue('genre')).toBe('horror')
|
||||
expect(getInputValue('rating-score')).toBe('5');
|
||||
expect(document.getElementById('rating-type-critic')?.hasAttribute('checked')).toBe(true)
|
||||
});
|
||||
});
|
||||
|
||||
function setInputValue(id: string, value: string) {
|
||||
|
||||
Reference in New Issue
Block a user