Introducing Swift Swap DynamicPage: for linear DOM state management
Swift Swap is developed and maintained by Christopher Nathaniel. Please note that Swift Swap / DynamicPage is in early ALPHA and is not ready for release. Many of the final features are subject to change. Its also worth noting that DynamicPage has renamed to Swift Swap; however this is still subject to change.
Download Swift Swap: https://www.npmjs.com/package/swift-swap
Install via NPM: npm i swift-swap;
Managing states and facilitating dynamic page reloads are indispensable tasks. DynamicPage is a powerful JavaScript library designed to streamline these processes and empower developers with enhanced control over their web applications. In this comprehensive guide, we’ll delve into the features, functionalities, and benefits of DynamicPage.
Understanding DynamicPage
At its core, DynamicPage is a versatile JavaScript library that simplifies state management and facilitates dynamic page rendering. DynamicPage empowers developers to effortlessly handle state changes and trigger dynamic page reloads, enhancing the user experience and improving application performance.
Key Features and Functionalities
DynamicPage offers a range of features and functionalities designed to optimize frontend development workflows:
- State Management: With DynamicPage, developers can easily manage application states, ensuring consistency and reliability across various components.
- Dynamic Page Reloads: The library facilitates dynamic page reloads, allowing developers to update content dynamically without the need for full page refreshes.
- Event Listener Management: DynamicPage includes a robust event listener manager, enabling developers to efficiently handle user interactions and trigger relevant actions.
- Component Rendering: Developers can define and render components dynamically, enhancing code modularity and scalability.
Implementation Example
Let’s take a closer look at how DynamicPage can be implemented in a real-world scenario:
import { DynamicPage } from 'swift−swap/src/PageFlow.js';import EventListenerManager from './js/libraries/EventListenerManager';import header from './header';const eventManagerListener = new EventListenerManager();const state = {}let renderList = [() => { eventManagerListener.removeAll(); document.querySelectorAll('a').forEach(link => { eventManagerListener.add(link, 'click', (event) => { event.preventDefault(); document.body.classList.add('page−transition'); window.scrollTo({ top: 0, behavior: 'instant'}); setTimeout(() => { window.history.pushState({}, '', link.href); dynamicPage._makeRequest(link.href); // Make Request and Render }, 1000); }); });}];renderList = [...renderList, () => { setTimeout(() => document.body.classList.remove('page−transition'), 800);}];renderList = [...renderList, Header({ val: state, parent: 'header'}).RenderComponent];const dynamicPage = new DynamicPage({source: 'DynamicPage', target: 'App'}, renderList, true);dynamicPage._makeRequest(window.location.href); // Make Request and Render index.html to the page
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF−8"> <meta name="viewport" content="width=device−width, initial−scale=1.0"> <title>My Swift−Swap Demo</title></head><body> <a href="index.html">Home</a> <a href="about.html">About</a> <App class="container"> <DynamicPage> <h1>Hello, World!</h1> </DynamicPage> </App></body></html>
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF−8"> <meta name="viewport" content="width=device−width, initial−scale=1.0"> <title>About | My Swift−Swap Demo</title></head><body> <a href="index.html">Home</a> <a href="about.html">About</a> <App class="container"> <DynamicPage> <h1>About us!</h1> </DynamicPage> </App></body></html>
import { PageFlow, HTMLflow, uuid, DatasetHandler } from 'swift−swap/src/PageFlow.js';// HTML Rendered Moduleconst header = ({ val, parent }) => { // Add More items to State const localState = { ...val, switchName : 'Clear Inputs', switchValue : '' }; // Include PageFlow Dependancies const [_, variables] = new PageFlow(parent, { ...localState}); // Initialise Component const dataset = new DatasetHandler(document.querySelector('dataset')).parseData(); // Typical Functions const functions = { testCallback: (_this) => { variables.switchName = 'different'; return variables.switchName }, clearCallback: (_this) => { return ' '; }, defaultCallback: (_this) => { return '12'; } } // Render Component (Loops the HTML values) const RenderComponent = () => { const id = uuid(); document.querySelectorAll(parent + ' [html]').forEach((item) => { HTMLflow(_, {item}, functions, id); // HTMLflow renders components }); _.render(); }; return { RenderComponent: RenderComponent // Return the Render Component };};export { header as default }
<div class="header"> <div class="function"> {% for post in posts %} <a href="{{ post.link }}">{{ post.title }}</a> <a html class="is−counter" @ref="11_{{loop.index}}" @update="44" @trigger="click" callback="testCallback" postCallback="testCallback" defaultCallback="defaultCallback">{{'{{ switchName }}'}}</a> {% endfor %} </div></div>
npm i swift−swap
Page Reload Functionality with JavaScript Routing
// Initialize EventListenerManager
const eventManagerListener = new EventListenerManager();
Here, we initialize an instance of the EventListenerManager
class from our custom library. This manager helps us efficiently manage event listeners attached to DOM elements, ensuring proper handling of user interactions.
// Define initial state
const state = {};
We define an empty object state
to represent the initial state of our application. This object will hold various pieces of data that may change over time, allowing us to maintain a consistent state throughout our application.
// Define render list
let renderList = [() => {
eventManagerListener.removeAll();
document.querySelectorAll('a').forEach(link => {
eventManagerListener.add(link, 'click', (event) => {
event.preventDefault();
dynamicPage._makeRequest(link.href); // Make Request and Render
});
});
}];
In this section, we define a list of functions called renderList
. Each function in this list is responsible for rendering a specific component or handling a particular aspect of the application’s functionality. Here, we add an event listener to all anchor (<a>
) elements on the page. When a user clicks on a link, we prevent the default action (navigating to a new page) and instead trigger a dynamic page request using DynamicPage’s _makeRequest
method.
// Add additional components to render list
renderList = [...renderList, organism00({ val: state, parent: '.organism-00 .function' }).RenderComponent];
renderList = [...renderList, Header({ val: state, parent: 'header'}).RenderComponent];
These lines add additional components to the renderList
. We use functions provided by our library to render specific components (organism00
and Header
) with their respective parent elements.
// Initialise DynamicPage
const dynamicPage = new DynamicPage({source: 'DynamicPage', target: 'App'}, renderList, true);
dynamicPage._makeRequest('/'); // Make Request and Render index.html to the page
Finally, we initialise an instance of DynamicPage
by passing the source element (DynamicPage
) and the target element (App
) where the rendered content will be placed. We also pass the renderList
to specify the rendering order of components. Lastly, we make a request to render the initial content (e.g., index.html
) to the page using the _makeRequest
method.
State Management Functionality
import { PageFlow, HTMLflow, uuid, DatasetHandler } from 'swift-swap/src/PageFlow.js';
Here, we’re importing several modules (PageFlow
, HTMLflow
, uuid
, and DatasetHandler
) from a JavaScript file located at 'swift-swap/src/PageFlow.js'
. These modules are essential for managing page flow, rendering HTML components, generating unique identifiers (UUIDs), and handling dataset attributes.
Organism00 Function:
const organism00 = ({ val, parent }) => {
// Function body...
};
This function defines a component named organism00
. It takes an object as an argument with properties val
and parent
, which represent the component’s state and parent element selector, respectively.
Local State Initialization:
const localState = {
...val,
switchName : 'Clear Inputs12',
switchValue : ''
};
Here, we initialize a local state object localState
by spreading the values of the val
object (which represents the component’s state passed as an argument) and adding additional properties switchName
and switchValue
.
PageFlow Initialization:
const [_, variables] = new PageFlow(parent, { ...localState});
This line initializes the PageFlow
module with the specified parent
element selector and the localState
object as initial state. It returns two variables: _
, which represents the PageFlow
instance, and variables
, which holds the component’s state.
Dataset Initialization:
const dataset = new DatasetHandler(document.querySelector('dataset')).parseData();
Here, we initialize the DatasetHandler
module with the <dataset>
element found in the document. The parseData()
method is then called to parse and handle dataset attributes within the dataset element.
Functions Object:
const functions = {
testCallback: (_this) => {
variables.switchName = 'different';
return variables.switchName
},
clearCallback: (_this) => {
return ' ';
},
defaultCallback: (_this) => {
return '12';
}
}
This object defines callback functions that can be used in HTML elements as attributes (callback
, postcallback
, defaultcallback
) to handle specific events or actions triggered by those elements.
RenderComponent Function:
const RenderComponent = () => {
const id = uuid();
document.querySelectorAll(parent + ' [html]').forEach((item) => {
HTMLflow(_, {item}, functions, id);
});
_.render();
};
This function renders the component by looping through all HTML elements within the parent element selector (parent
) that have an html
attribute. It uses the HTMLflow
module to render the components and then calls the render()
method of the PageFlow
instance (_
) to ensure the state is up to date and the UI is re-rendered.
Return Statement:
return {
RenderComponent: RenderComponent
};
The organism00
function returns an object with a RenderComponent
property, which holds the RenderComponent
function. This allows other parts of the application to use and render this component.
Export Statement:
export { organism00 as default }
Finally, the organism00
component is exported as the default export of the module, making it accessible to other parts of the application.
Conclusion: DynamicPage represents a shift in frontend development, offering developers an intuitive and efficient solution for managing states and facilitating dynamic page reloads. By leveraging its robust features and functionalities, developers can enhance user experiences, improve application performance, and streamline development workflows.