Skip to content

Commit

Permalink
Custom web component: Converting React elements to HTML (#654)
Browse files Browse the repository at this point in the history
Co-authored-by: Ole Martin Handeland <[email protected]>
  • Loading branch information
olemartinorg and Ole Martin Handeland authored Nov 15, 2022
1 parent dd5b821 commit 9b6573b
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 2 deletions.
13 changes: 12 additions & 1 deletion schemas/json/layout/layout.schema.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"type": "string",
"title": "Type",
"description": "The component type.",
"enum": ["AddressComponent", "AttachmentList", "Button", "Checkboxes", "Datepicker", "Dropdown", "FileUpload", "FileUploadWithTag", "Group", "Header", "Image", "Input", "InstantiationButton", "Likert", "MultipleSelect", "NavigationButtons", "NavigationBar", "Panel", "Paragraph", "PrintButton", "RadioButtons", "Summary", "TextArea"]
"enum": ["AddressComponent", "AttachmentList", "Button", "Checkboxes", "Custom", "Datepicker", "Dropdown", "FileUpload", "FileUploadWithTag", "Group", "Header", "Image", "Input", "InstantiationButton", "Likert", "MultipleSelect", "NavigationButtons", "NavigationBar", "Panel", "Paragraph", "PrintButton", "RadioButtons", "Summary", "TextArea"]
},
"required": {
"title": "Required",
Expand Down Expand Up @@ -122,6 +122,7 @@
{ "if": {"properties": {"type": { "const": "AddressComponent"}}}, "then": { "$ref": "#/definitions/addressComponent"}},
{ "if": {"properties": {"type": { "const": "AttachmentList"}}}, "then": { "$ref": "#/definitions/attachmentListComponent"}},
{ "if": {"properties": {"type": { "const": "Checkboxes"}}}, "then": { "$ref": "#/definitions/radioAndCheckboxComponents"}},
{ "if": {"properties": {"type": { "const": "Custom"}}}, "then": { "$ref": "#/definitions/customComponent"}},
{ "if": {"properties": {"type": { "const": "Datepicker"}}}, "then": { "$ref": "#/definitions/datepickerComponent"}},
{ "if": {"properties": {"type": { "const": "Dropdown"}}}, "then": { "$ref": "#/definitions/selectionComponents"}},
{ "if": {"properties": {"type": { "const": "FileUpload"}}}, "then": { "$ref": "#/definitions/fileUploadComponent"}},
Expand Down Expand Up @@ -598,6 +599,16 @@
}
}
},
"customComponent": {
"properties": {
"tagName": {
"type": "string",
"title": "Tag name",
"description": "Web component tag name to use"
}
},
"required": ["tagName"]
},
"summaryComponent": {
"properties": {
"componentRef": {
Expand Down
4 changes: 4 additions & 0 deletions src/altinn-app-frontend/setupTests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'jest';
import '@testing-library/jest-dom/extend-expect';
import { TextEncoder, TextDecoder } from 'util';

import type { IAltinnWindow } from 'src/types';

Expand All @@ -25,3 +26,6 @@ altinnWindow.app = 'test';
jest.setTimeout(10000);

jest.mock('axios');

(global as any).TextEncoder = TextEncoder;
(global as any).TextDecoder = TextDecoder;
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe('CustomWebComponent', () => {
const element = screen.getByTestId('test-component');
expect(element.id).toEqual('test-component');
expect(element.getAttribute('data-CustomAttributeWithJson')).toEqual(JSON.stringify(jsonAttributeValue));
expect(element.getAttribute('data-CustomAttributeWithReact')).toEqual('<span>Hello world</span>');
});

it('should render the component with passed props as attributes', () => {
Expand Down Expand Up @@ -58,6 +59,7 @@ describe('CustomWebComponent', () => {
title: 'title',
},
'data-CustomAttributeWithJson': jsonAttributeValue,
'data-CustomAttributeWithReact': <span>Hello world</span>,
};

const resources = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import ReactDOMServer from 'react-dom/server';

import { useAppSelector } from 'src/common/hooks';
import type { PropsFromGenericComponent } from 'src/components';
Expand Down Expand Up @@ -64,7 +65,9 @@ function CustomWebComponent({
const propsAsAttributes: any = {};
Object.keys(passThroughProps).forEach((key) => {
let prop = passThroughProps[key];
if (['object', 'array'].includes(typeof prop)) {
if (React.isValidElement(prop)) {
prop = ReactDOMServer.renderToStaticMarkup(prop);
} else if (['object', 'array'].includes(typeof prop)) {
prop = JSON.stringify(passThroughProps[key]);
}
propsAsAttributes[key] = prop;
Expand Down

0 comments on commit 9b6573b

Please sign in to comment.