Skip to content

Commit

Permalink
Allow Telepath's widget rendering to take options
Browse files Browse the repository at this point in the history
This allows us to pass extra data for the widget to use in a
backwards-compatible way.

Co-Authored-By: LB Johnston <mail@lb.ee>
  • Loading branch information
Stormheg and lb- committed Jul 27, 2023
1 parent dec8ec4 commit 9ed3b6b
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 5 deletions.
31 changes: 27 additions & 4 deletions client/src/entrypoints/admin/telepath/widgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@
import { gettext } from '../../../utils/gettext';

class BoundWidget {
constructor(element, name, idForLabel, initialState, parentCapabilities) {
constructor(
element,
name,
idForLabel,
initialState,
parentCapabilities,
options,
) {
var selector = ':input[name="' + name + '"]';
this.input = element.find(selector).addBack(selector); // find, including element itself
this.idForLabel = idForLabel;
this.setState(initialState);
this.parentCapabilities = parentCapabilities || new Map();
this.options = options;
}

getValue() {
Expand Down Expand Up @@ -49,10 +57,24 @@ class Widget {

boundWidgetClass = BoundWidget;

render(placeholder, name, id, initialState, parentCapabilities) {
render(
placeholder,
name,
id,
initialState,
parentCapabilities,
options = {},
) {
var html = this.html.replace(/__NAME__/g, name).replace(/__ID__/g, id);
var idForLabel = this.idPattern.replace(/__ID__/g, id);
var dom = $(html);

// Add any extra attributes we received to the HTML of the widget
if (typeof options?.attributes === 'object') {
Object.entries(options.attributes).forEach(([key, value]) => {
dom.attr(key, value);
});
}
$(placeholder).replaceWith(dom);
// eslint-disable-next-line new-cap
return new this.boundWidgetClass(
Expand All @@ -61,6 +83,7 @@ class Widget {
idForLabel,
initialState,
parentCapabilities,
options,
);
}
}
Expand Down Expand Up @@ -349,7 +372,7 @@ class DraftailRichTextArea {
this.options = options;
}

render(container, name, id, initialState, parentCapabilities) {
render(container, name, id, initialState, parentCapabilities, options = {}) {
const input = document.createElement('input');
input.type = 'hidden';
input.id = id;
Expand All @@ -363,7 +386,7 @@ class DraftailRichTextArea {

const boundDraftail = new BoundDraftailWidget(
input,
this.options,
{ ...options, ...this.options },
parentCapabilities,
);

Expand Down
27 changes: 26 additions & 1 deletion client/src/entrypoints/admin/telepath/widgets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ window.comments = {

describe('telepath: wagtail.widgets.Widget', () => {
let boundWidget;
let widgetDef;

beforeEach(() => {
// Create a placeholder to render the widget
document.body.innerHTML = '<div id="placeholder"></div>';

const widgetDef = window.telepath.unpack({
widgetDef = window.telepath.unpack({
_type: 'wagtail.widgets.Widget',
_args: [
'<input type="text" name="__NAME__" maxlength="255" id="__ID__">',
Expand Down Expand Up @@ -60,6 +61,30 @@ describe('telepath: wagtail.widgets.Widget', () => {
boundWidget.focus();
expect(document.activeElement).toBe(document.querySelector('input'));
});

test('it should support options with attributes', () => {
document.body.innerHTML = '<div id="placeholder"></div>';
boundWidget = widgetDef.render(
document.getElementById('placeholder'),
'the-name',
'the-id',
'The Value',
{},
{
attributes: {
'maxLength': 512,
'aria-describedby': 'some-id',
'required': '',
},
},
);

const input = document.querySelector('input');

expect(input.maxLength).toBe(512);
expect(input.getAttribute('aria-describedby')).toBe('some-id');
expect(input.required).toBe(true);
});
});

describe('telepath: wagtail.widgets.RadioSelect', () => {
Expand Down

0 comments on commit 9ed3b6b

Please sign in to comment.