Joomla 4 Tips and Tricks: Data Table Toggles

From Joomla! Documentation

Introduction

This tip comes from a component that has a data list that looks more a like a spreadsheet than a database table. Some of the cells have simple content such as Yes/No values that have to be changed from time to time, often daily. The data entry form has many fields spread over several tabs and it is a bit tedious to open the form, find the right field in the right tab and change No to Yes. The users wanted a simple method to make such changes. A click on No to change it to Yes in the data table. The Joomla articles list has something similar to change Published to Unpublished or Featured to Unfeatured. However, that also causes a page reload which is undesirable for a Yes/No change as it causes loss of place.

Here is a snip from of a list view table:

Table Yes/No Buttons

The default.php List View

This is where the code goes to load the javascript file near the top:

/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $this->document->getWebAssetManager();
$wa->useScript('com_mycompoent.myview');

And further down the code for the toggle buttons. This is one example:

				<td class="text-center">
					<button 
						id="onhold_<?php echo $item->id;?>" 
						class="yntoggle btn btn-sm btn-secondary">
						<?php echo Text::_($yesno[$item->on_hold]); ?>
					</button>
				</td>

The myview.js Javascript file

The javascript file needs an event listener for each toggle button and an async function to interact with the server:

// ===== Yes/No toggle =====

let toggles = document.getElementsByClassName('yntoggle');
if (toggles) {
	for (let i = 0; i < toggles.length; i++) {
		toggles[i].addEventListener('click', toggler, false);
	}
}

async function toggler(event) {
	event.preventDefault();
	let tds = document.querySelectorAll('td.update-ok');
	tds && tds.forEach(function (item, index) {
		item.classList.remove('update-ok');
	});
	tds = document.querySelectorAll('td.update-dud');
	tds && tds.forEach(function (item, index) {
		item.classList.remove('update-dud');
	});
	let id = this.id;
	let parts = id.split('_');
	let td = this.closest('td');
	let oldvalue = this.textContent.trim;
	const token = Joomla.getOptions('csrf.token', '');
	const url = 'index.php?option=com_mycomponent&task=myview.yntoggle&' + token + '=1';
	let data = new URLSearchParams();
	data.append(`field`, parts[0]);
	data.append(`item_id`, parts[1]);
	data.append(`oldvalue`, oldvalue);
	const options = {
		method: 'POST',
		body: data
	}
	let response = await fetch(url, options);
	if (!response.ok) {
		td.classList.add('update-dud');
		throw new Error (Joomla.Text._('COM_MYCOMPONENT_JS_ERROR_STATUS') + `${response.status}`);
	} else {
		let result = await response.text();
		this.textContent = result;
		td.classList.add('update-ok');
	}
}

Server Script

This code is in src/Controller/MyviewController.php Some sensitive parts of the query have been left out here and it was inherited from Joomla 3 and is not quite right for Joomla 4.

	public function yntoggle() {
		Session::checkToken( 'post' ) or die( 'Is your session expired? Try a page reload!'); //|Invalid Token' );
		$app = Factory::getApplication();
		$item_id = $app->input->get('item_id', 0, 'int');
		if (empty($item_id)) {
			die( 'NOTOK #1');
		}
		$field = $app->input->get('field', '', 'word');
		$oldvalue = $app->input->get('oldvalue', '', 'word');
		// check for allowed things to toggle
		$db = Factory::getDbo();
		$query = $db->getQuery(true);
		...
		$db->execute();
		// get the updated value
		$query = $db->getQuery(true);
		...
		$db->setQuery($query);
		$new_value = $db->loadResult();
		exit($new_value ? 'Yes' : 'No');
	}

CSS

A little but of css is needed to show that the request has been executed and a result returned:

.update-ok {
	background-color: #eeffee !important;
	background-image: url(tick-12.png) !important;
	background-repeat: no-repeat !important;
	background-position: 95% 0 !important;
	border-color: #009900 !important;
}

.update-dud {
	background-color: #ffeeee !important;
	background-image: url(cross-12.png) !important;
	background-repeat: no-repeat !important;
	background-position: 95% 0 !important;
	border-color: #990000 !important;
}

Result

Table Yes/No Buttons Toggle Result

Parent Links

Back to J4.x:Tips and Tricks for Joomla 4 Developers