Implement HTML <template> element

Please implement HTML ‘template’ element so I can stop using Custom Code’s with alpinejs.

Thanks

Russ

Thank you for the suggestion! As I see it if we had a template element it would behave exactly like custom code, so you would double click to edit its contents in the editor panel. Do you have suggestions on how it could be made more convenient for you?

Hi Martin

Ideally the same way that you’ve implemented <div>. A common pattern is to use Custom Codes like:

Custom Code containing <template x-if="status !== 'Running'">

some DOM

Custom Code containing </template>

It would be much easier to read the DOM and just see the <template>s with the x-* attributes directly.

You don’t need to have the template in the DOM so no need for custom code inside BSS

here is an example with a simple table

html

<div class="container">
	<div class="row">
			<div class="col">
					<div class="table-responsive">
							<table class="table" id="producttable">
								<thead>
									<tr>
										<th>UPS CODE</th>
										<th>Product Name</th>
									</tr>
								</thead>
								<tbody></tbody>
							</table>
					</div>
			</div>
	</div>
</div>

example with a data object
javascript

const data = [
  {
    upscode: '1235646565',
    product: 'Stuff',
  },
  {
    upscode: '0384928528',
    product: 'Acme Kidney Beans 2',
  },
];

function createTableRow(data) {
  const row = document.createElement('tr');
  const cell1 = document.createElement('td');
  const cell2 = document.createElement('td');
  cell1.textContent = data.upscode;
  cell2.textContent = data.product;
  row.appendChild(cell1);
  row.appendChild(cell2);
  return row;
}

function appendRowsToTableBody(tbody, rows) {
  rows.forEach((row) => tbody.appendChild(row));
}

const tbody = document.querySelector('tbody');
if (tbody) {
  if ('content' in document.createElement('template')) {
    const template = document.createElement('template');
    template.innerHTML = `<tr><td></td><td></td></tr>`;
    const rows = data.map((post) => {
      const clone = template.content.cloneNode(true);
      const cells = clone.querySelectorAll('td');
      cells[0].textContent = post.upscode;
      cells[1].textContent = post.product;
      return clone;
    });
    appendRowsToTableBody(tbody, rows);
  } else {
    const rows = data.map(createTableRow);
    appendRowsToTableBody(tbody, rows);
  }
} else {
  console.error('Table body not found');
}

example if fetching the data

javascript

async function fetchData(url) {
 try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    return data;
 } catch (error) {
    console.error('There was a problem with the fetch operation:', error);
    return []; // Return an empty array or handle the error as needed
 }
}

fetchData('assets/js/data.json').then(fetchedData => {
 if (fetchedData.length > 0) {
    const tbody = document.querySelector('tbody');
    if (tbody) {
      if ('content' in document.createElement('template')) {
        const template = document.createElement('template');
        template.innerHTML = `<tr><td></td><td></td></tr>`;
        const rows = fetchedData.map(post => {
          const clone = template.content.cloneNode(true);
          const cells = clone.querySelectorAll('td');
          cells[0].textContent = post.upscode;
          cells[1].textContent = post.product;
          return clone;
        });
        appendRowsToTableBody(tbody, rows);
      } else {
        const rows = fetchedData.map(createTableRow);
        appendRowsToTableBody(tbody, rows);
      }
    } else {
      console.error('Table body not found');
    }
 } else {
    console.log('No data to display');
 }
}).catch(error => {
 console.error('Error fetching data:', error);
});

function createTableRow(data) {
 const row = document.createElement('tr');
 const cell1 = document.createElement('td');
 const cell2 = document.createElement('td');
 cell1.textContent = data.upscode;
 cell2.textContent = data.product;
 row.appendChild(cell1);
 row.appendChild(cell2);
 return row;
}

function appendRowsToTableBody(tbody, rows) {
 rows.forEach(row => tbody.appendChild(row));
}

Hi kuligaposten

Unless I’m missing something, I’m not sure how your answer relates to AlpineJS…?

@rm5170

I show you an example with a simple table
here is an example with alpineJs
look at the source code no <template> in the DOM

Thanks for your response.

‘x-for’ and ‘x-if’ needs to be declared on a template as per for — Alpine.js and if — Alpine.js

Currently the only way to do that is through Custom Codes I think.

Alpine.js is a great tool for css framework based on utilities or if you write all your css by yourself

Bootstrap is a component based framework and comes with javascript as well

Alpine.js x-if example

<div x-data="{ open: false }">
    <button @click="open = ! open">Expand</button>
    <template x-if="open">
	  <p>Content...</p>
    </template>
</div>

In Bootstrap Studio you drop a bootstrap collapse component which do the same thing

If you want a dropdown you drop a bootstrap dropdown component,
I don’t think you use an Alpine.js UI component for that

The same goes for other javascript components in bootstrap like

  • Accordion
  • Alerts
  • Carousel
  • Collapse
  • Dropdowns
  • Modal
  • Navbar
  • Nav & tabs
  • Offcanvas
  • Popover
  • Toast
  • Tooltips

you don’t use Alpine.js UI components for that, you use bootstrap components

Why are you using Alpine.js with Bootstrap?

if you had inspected the example you would have seen there is no custom code with a <template>
quite pointless to show you an example if you don’t look at it

I support rm5170’s request for a <template> tag:

You cannot replace the AlpineJs framework with Bootstrap components. These are two completely different things and and Bootstrap cannot do what AlpineJs can do. Most people do use a framework besides Bootstrap.
@kuligaposten, you are providing a javascript example that manipulates the DOM as a workaround. This is about 40 lines of code. It is a one-liner with AlpineJs. That is why we are using frameworks. Writing everything by hand is not an option.

It is a problem for Bootstrap Studio that it does not integrate well with frameworks. First I thought that - with AlpineJs I had a compatible framework found - until I encountered the missing <template> tag. It would be a great advantage for Bootstrap Studio to make it compatible so that you can tell people: “If you need a framework along with Bootstrap Studio, then there is AlpineJs.”

It is probably not a big deal to support a <template> tag. It is like a <div> tag, but with the possibility to embrace everything. The <div> tag cannot embrace a <tr> for example in Bootstrap Studio. The same applies to the Custom Code element. That is why the Custom Code element can not be used as a workaround for the missing <template> tag.

Above, the link to your “example with AlpineJs” does not work, so I did not consider it. Any other suggestion that makes AlpineJs work with Bootstrap Studio is welcome, too.

Here have a look bootstrap.js and alpine.js on the same page doing the same thing. No custom code

Thank you, kuligaposten. You provided two examples to illustrate how to create list GUI components with data from an array. The first example uses AlpineJs with <template x-for=…> . The second example uses the Bootstrap group-list component. Both examples require additional javascript code. The javascript in the AlpineJs example creates the <template x-for=…> tag. The javascript also creates the HTML for the list items in both examples.

The examples have the same disadvantages in common:
a) The GUI for the list items is not created by Bootstrap Studio but by javascript. Why are we using Bootstrap Studio when we have to create html manualy and then put it in a javascript string?
b) For every list on the GUI you have add such specific code again.
c) Most developers will not be able to come up with such a solution on their own. It requires quite a bit of knowledge and effort.

This is what we need: Being able to design the GUI with Bootstrap Studio and then make the lists in the GUI dynamic so that list items are created with content from a collection/database. The list items can be complex components with buttons and other elements.

If you are honest you have to admit that both your solutions do not solve this in a practical way.

Bootstrap Studio greatly helped me with my GUI implementation. I can highly recommend it for static web sites. But when you want to make your website dynamic you have to come up with some tedious workaround. Support for the standard html <template> tag would simplify things a lot.

try that one…

made it specifically for client side html document in which you have no control during build time(eg: published using bss hosted site)…

for now I didn’t make a prebuild… you have to build it yourself…
I put alpine class and methods for x-if and x-for as one of the examples…

no need to use custom code, just add some attribute on the element…

however since it’s a dom manipulation using real dom not template, expect some flickering on slow machine and or heavy element…

ps: I’m sorry I’m on my phone, ask away for examples if needed, will try to provide, when I’m on my desktkop

You can use Alpine and htmx in Bootstrap Studio without write any javascript yourself