Hi i need an example on how to implement a simple on / off toggler in a Joomla 4/5 Custom Component's list view. I've tried the following code but i did not get any reaction in the model / idk how to forward it from controller:
The Project: Basic structure of a listview of items and edit of items Models are called "RegistrationsModel" and "RegistrationModel".
In the listview of RegistrationModels I've rendered the following (in development):
...
<td class="text-center">
<?php
$task = $item->payment_status == 1 ? 'setunpaid' : 'setpaid';
$class = $item->payment_status == 1 ? 'fas fa-check-circle text-success' : 'fas fa-times-circle text-danger';
$label = $item->payment_status == 0 ? 'SET_PAID' : 'SET_UNPAID';
$action = Text::_($label);
echo '<a href="#" onclick="return Joomla.listItemTask(\'cb' . $i . '\',\'' . 'registration.' . $task . '\')" title="' . $action . '">';
echo '<i class="' . $class . ' fa-lg" title="' . Text::_($label) . '"></i>';
echo '</a>';
?>
</td>
...
Controllers are called "RegistrationsController" (extends AdminController) and "RegistrationController" (extends FormController). The RegistrationModel extends the AdminModel
In the model I've placed these methods:
...
public function setpaid(){
error_log('setPaid called');
}
public function setunpaid(){
error_log('setUnpaid called');
}
...
My RegistrationController:
class RegistrationController extends FormController
{
protected $view_list = 'registrations';
protected $default_view = 'registration';
public function setpaid($data = null)
{
error_log(print_r($data, true));
error_log('setpaid in controller');
return true;
}
public function setunpaid($data = null)
{
error_log(print_r($data, true));
error_log('setunpaid in controller');
return true;
}
}
In the controller the log gets called, but: How can i forward the call from the controller to the model / identify the item in the model? "$data" is empty / null in Controller...
And (maybe solved automatically) when clicking the icon the list view disapears and shows a blank view now.
Thanks for guiding me into the right direction
*** Edit: *** Thanks to Sharky's answer below the Controller looks now like this:
public function setpaid()
{
$ids = (array) $this->input->get('cid', [], 'int');
$this->setPaymentStatus($ids, 1);
}
public function setunpaid()
{
$ids = (array) $this->input->get('cid', [], 'int');
$this->setPaymentStatus($ids, 0);
}
protected function setPaymentStatus($ids, $status)
{
$model = $this->getModel('Registration');
$model->setPaymentStatus($ids, $status);
}
And in the Model:
public function setPaymentStatus($arrayOfIds, $status): void
{
$db = $this->getDbo();
$query = $db->getQuery(true);
$query->update($db->quoteName('#__com_componentname_registrations'));
$query->set($db->quoteName('payment_status') . ' = ' . $status);
$query->where($db->quoteName('id') . ' IN (' . implode(',', $arrayOfIds) . ')');
$db->setQuery($query);
$db->execute();
}
When clicking on the icon it sets the new value - but the page got reloaded and the table is then gone, what did I have to write to block this behavior / to reload the list with the filters still set?
Edit 2: Ok got it now, I modified my setPayment Method in the Controller:
protected function setPaymentStatus($ids, $status)
{
$model = $this->getModel('Registration');
$model->setPaymentStatus($ids, $status);
// Force a re-rendering of the listview and keep filter and current page thanks to input
$url = 'index.php?option=com_componentname&view=registrations';
$this->setRedirect(Route::_($url, false));
}
Thanks to the input Joomla keeps the filter / listposition so the redirect itself is enough now.