This may be useful to some who are familiar with React and want to make re-usable components within their applications. I’ve only tried this with React, however, there should be no reason why you can’t do this with other frontend frameworks/libraries.
To start of with, we’ll build a simple counter button to get a grasp of the setup and syntax, then we’ll build something more real-world, a toast component.
To start with, on the app initialization, we’re pulling in a few libraries, and binding html
and Components
as global variables.
html
is giving us JSX syntax, so we can use JS in our code. Components
is self explanatory, this will contain a list of objects containing our components.
KnackInitAsync = function ($, callback) {
window.$ = $;
LazyLoad.js(
[
"https://unpkg.com/htm@2.2.1",
"https://unpkg.com/react@17/umd/react.production.min.js",
"https://unpkg.com/react-dom@17/umd/react-dom.production.min.js",
],
function () {
window.html = htm.bind(React.createElement);
window.Components = {};
callback();
}
);
};
Let’s start off by creating a Toggle
component which increments the count on click of the button and displays the count.
const { useState } = React;
// ...
window.Components = {
Toggle,
};
function Toggle() {
const [count, setCount] = useState(0);
return html`
<div>
<button onClick=${() => setCount(prev => prev + 1)}>Increase Count</button>
<div>Current count: ${count}</div>
</div>
`;
}
Now, in our render view function, we can bring in our Toggle
component from our Components
variable and render the component to a wrapper element.
$(document).on("knack-view-render.view_1", function (event, view, data) {
const { Toggle } = Components;
$("#view_1").append(`
<div id="toggleWrapper"></div>
`);
ReactDOM.render(
html`<${Toggle} />`,
document.querySelector("#toggleWrapper")
);
});
Now that we got an understanding how this works, let’s create something more real-world. In this example, we’ll create a toast notification component.
function ToastNotification({ heading, content }) {
window.Components = {
Toggle,
};
// ...
function ToastNotification({ heading, content }) {
return html`
<div class="toast-wrapper">
<div class="heading-wrapper">
<i class="fa fa-check-circle"></i>
<span class="toast-heading">${heading}</span>
</div>
<span class="toast-content">${content}</span>
</div>
`;
}
Now we can create a function, which renders our ToastNotification component, and trigger the function in our Knack render view function.
function displayToast(heading, content) {
const { ToastNotification } = Components;
$("body").append(`<div id="toastNotification"></div>`);
ReactDOM.render(
html` <${ToastNotification} heading=${heading} content=${content} /> `,
document.querySelector(`#toastNotification`)
);
setTimeout(() => {
$("#toastNotification").remove();
}, 2500);
}
$(document).on("knack-view-render.view_1", function (event, view, data) {
displayToast("Success", "This is our success message");
});
And some basic css to display the toast message on the top right the screen.
.toast-wrapper {
width: 250px;
padding: 15px 25px;
color: #fff;
background: #22c55e;
display: inline-block;
position: fixed;
top: 20px;
right: 20px;
border-radius: 10px;
transition: all 0.4s ease-out;
}
.heading-wrapper {
display: flex;
align-items: center;
}
.heading-wrapper > i {
font-size: 18px;
margin-right: 8px;
}
.toast-heading {
font-size: 16px;
font-weight: 600;
}
.toast-content {
display: block;
}
These components don’t nessesarily need to be in Knack, and can be hosted externally and used in multiple projects.
Happy to provide more examples if people find this useful