Include a BSS DIV snippet, but not entire html file?

Hi forum,

I’ve got a form with a select that will show/hide many DIV’s based on what is selected.

Original topic here: Select component - use selects (dropdown) to display multiple other components?

The issue I’ve run into, is that this form’s select currently has 20 options, with the 20 corresponding DIV’s that are shown, or hidden based on that selection made.

The DIV’s in this case are a bit large with many input’s as well as up to 15 “Excel” type row’s with up to 25 inputs each row.

Of course, this means that all of those 20 large DIV’s are loaded whenever this page loads.

I’d like to switch from showing or hiding these DIV’s based on the selection…to including the respective content in the DIV (for only the selection made) as an include.

However, I don’t want to create an “.html” file for each of these DIV’s content because they are only structured with a Row component…and not the entire format because then of course there would be another set of html and body tags.

2 questions:

  1. Is there a way to create a file other than .html in BSS and use that to hold the include content? Perhaps a .txt file?

  2. I was thinking using Javascript to handle which file to include, however, there appears to be several other ways to accomplish this as well (including using IFRAME to inject the content of itself onto the parent page then remove itself) The Simplest Ways to Handle HTML Includes | CSS-Tricks - CSS-Tricks Thoughts on which method is best to use in conjunction with BSS?

Thank you.

You can have your forms and tables on a html page and dynamically load your components.
In the example below the components are on a component.html page, I’m fetching the components using two javascript modules
the ComponentLoader return a Promise so you can have a .then(…) if you need to dynamically add javascript or css
classes/classes.mjs

export class ComponentLoader {
  constructor(clearCache = false) {
    this.componentCache = '';
    this.clearCache = clearCache;
  }

  static clearCache() {
    ComponentLoader.componentCache = '';
  }

  static async fetchContent(baseUrl) {
    if (ComponentLoader.componentCache === '') {
      try {
        const response = await fetch(baseUrl);
        return (ComponentLoader.componentCache = await response.text());
      } catch (error) {
        throw new Error(`Error fetching content: ${error.message}`);
      }
    }

    return ComponentLoader.componentCache;
  }

  static async injectComponent(selector, target, baseUrl, clearCache) {
    try {
      if (clearCache) {
        this.clearCache();
      }

      const content = await this.fetchContent(baseUrl);
      const targetNode = document.querySelector(target);

      if (targetNode) {
        const parser = new DOMParser();
        const parsedDocument = parser.parseFromString(content, 'text/html');
        const clonedNode = parsedDocument
          .querySelector(selector)
          .cloneNode(true);
        targetNode.parentNode.replaceChild(clonedNode, targetNode);
        console.log('Component injected successfully.');
      } else {
        throw new Error(`Target node with selector "${selector}" not found.`);
      }
    } catch (error) {
      console.error('Error injecting component:', error);
      throw error;
    }
  }

  static loadComponentWithSelector(selector, target, baseUrl, clearCache) {
    return new Promise(async (resolve, reject) => {
      try {
        if (clearCache) {
          this.clearCache();
        }

        await this.injectComponent(selector, target, baseUrl, clearCache);
        resolve();
      } catch (error) {
        reject(error);
      }
    });
  }
}

How to use it
app.mjs

import {
  ComponentLoader,
  ParallaxBackground,
} from './classes/classes.mjs';

ComponentLoader.loadComponentWithSelector(
  '[data-hero]',
  '[data-hero]',
  'component.html',
  true
)
  .then(() => {
    new ParallaxBackground();
    console.log('Component loaded successfully.');
  })
  .catch((error) => {
    console.error('Error:', error);
  });
const formSelector = document.getElementById('formselector');
formSelector.addEventListener('change', () => {
  if (formSelector.value === '1') {
    ComponentLoader.loadComponentWithSelector(
      '[data-contactus]',
      '[data-form]',
      'component.html',
      false
    )
      .then(() => {
        // here you can add css or javascript if needed
        console.log('Component loaded successfully.');
      })
      .catch((error) => {
        console.error('Error:', error);
      });
  }
  if (formSelector.value === '2') {
    ComponentLoader.loadComponentWithSelector(
      '[data-table]',
      '[data-form]',
      'component.html',
      false
    )
      .then(() => {
        // here you can add css or javascript if needed
        console.log('Component loaded successfully.');
      })
      .catch((error) => {
        console.error('Error:', error);
      });
  }
    if (formSelector.value === '3') {
    ComponentLoader.loadComponentWithSelector(
      '[data-record2]',
      '[data-form]',
      'component.html',
      false
    )
      .then(() => {
        // here you can add css or javascript if needed
        console.log('Component loaded successfully.');
      })
      .catch((error) => {
        console.error('Error:', error);
      });
  }
    if (formSelector.value === '4') {
    ComponentLoader.loadComponentWithSelector(
      '[data-record3]',
      '[data-form]',
      'component.html',
      false
    )
      .then(() => {
        // here you can add css or javascript if needed
        console.log('Component loaded successfully.');
      })
      .catch((error) => {
        console.error('Error:', error);
      });
  }
});

Here is an example of the ComponentLoader
have a look

1 Like

Thanks for the reply and suggestion! Lots to mull over there.

So basically, sounds like adding < div class=“row” > (and the < table > stuff inside it) to a BSS *.html file, which would include a 2nd set of tags isn’t an issue.