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;
|
this._form = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
async connectedCallback() {
|
||||||
const formSlot = this.shadowRoot?.querySelector('slot[name="form"]') as HTMLSlotElement;
|
const formSlot = this.shadowRoot?.querySelector('slot[name="form"]') as HTMLSlotElement;
|
||||||
if (!formSlot) {
|
if (!formSlot) {
|
||||||
throw new Error('[Declaform] Error: "form" slot is unassigned.')
|
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()) {
|
for (const [name, inputs] of inputGroups.entries()) {
|
||||||
this._fields.push(new Field(name, inputs))
|
this._fields.push(new Field(name, inputs))
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
const src = this.getAttribute('src');
|
const src = this.getAttribute('src');
|
||||||
if (src) {
|
if (src) {
|
||||||
this.hydrateForm(src);
|
this.hydrateFromEndpoint(src);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get form() {
|
get form() {
|
||||||
@@ -197,6 +196,12 @@ export class Declaform extends HTMLElement {
|
|||||||
};
|
};
|
||||||
populateFields(obj, '');
|
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);
|
customElements.define('decla-form', Declaform);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
//import '../declaform';
|
|
||||||
import { Declaform } from '../declaform';
|
import { Declaform } from '../declaform';
|
||||||
|
|
||||||
const MOVIE_FORM = `
|
const MOVIE_FORM_NO_SRC = `
|
||||||
<decla-form id="form">
|
<decla-form id="form">
|
||||||
<form slot="form">
|
<form slot="form">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
@@ -32,14 +31,49 @@ const MOVIE_FORM = `
|
|||||||
</decla-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', () => {
|
describe('Declaform', () => {
|
||||||
|
afterEach(() => {
|
||||||
|
document.body.innerHTML = '';
|
||||||
|
})
|
||||||
|
|
||||||
it('Should mount.', () => {
|
it('Should mount.', () => {
|
||||||
document.body.innerHTML = MOVIE_FORM;
|
document.body.innerHTML = MOVIE_FORM_NO_SRC;
|
||||||
expect(document.getElementById('form')).toBeTruthy();
|
expect(document.getElementById('form')).toBeTruthy();
|
||||||
})
|
})
|
||||||
|
|
||||||
it('.toObject() should serialize form into a JS object', () => {
|
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;
|
const form = document.getElementById('form') as Declaform;
|
||||||
setInputValue('name', 'Monty Python');
|
setInputValue('name', 'Monty Python');
|
||||||
setInputValue('genre', 'comedy');
|
setInputValue('genre', 'comedy');
|
||||||
@@ -57,7 +91,7 @@ describe('Declaform', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('.hydrate() should populate input fields from a JS object', () => {
|
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;
|
const form = document.getElementById('form') as Declaform;
|
||||||
form.hydrate({
|
form.hydrate({
|
||||||
name: 'Jaws',
|
name: 'Jaws',
|
||||||
@@ -71,7 +105,30 @@ describe('Declaform', () => {
|
|||||||
expect(getInputValue('genre')).toBe('horror')
|
expect(getInputValue('genre')).toBe('horror')
|
||||||
expect(getInputValue('rating-score')).toBe('5');
|
expect(getInputValue('rating-score')).toBe('5');
|
||||||
expect(document.getElementById('rating-type-critic')?.hasAttribute('checked')).toBe(true)
|
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) {
|
function setInputValue(id: string, value: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user