Introducing Swift Swap DynamicPage: for linear DOM state management

ByChristopher Nathaniel |

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:

Swift Swap
app.js
index.html
about.html
header.js
header.twig
install.sh
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 Module
const 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.

create build imagine design code grow enhance innovate inspire prototype debug wireframe integrate optimise performance scalability UI UX
0