J3.x

J3.x: Entwickeln einer MVC-Komponente / Hinzufügen eines Modals

From Joomla! Documentation

Revision as of 13:01, 13 January 2019 by Pete71 (talk | contribs) (Created page with "== Felddefinition ==")
Joomla! 
3.x
Tutorial
Entwicklung einer MVC Komponente

Hinzufügen einer variablen Anfrage zum Menütyp

Benutzung der Datenbank

Backend-Grundlagen

Hinzufügen von Sprachen

Hinzufügen von Aktionen im Backend

Hinzufügen von Dekorationen zum Backend

Hinzufügen von Validierungen

Hinzufügen von Kategorien

Hinzufügen einer Konfiguration

  1. Hinzufügen von ACL

Hinzufügen eines Installations-/Deinstallations-/Aktualisierungs-Skriptes

Hinzufügen eines Formulars im Frontend

  1. Hinzufügen von Bildern
  2. Hinzufügen von Karten
  3. Hinzufügen von AJAX
  4. Hinzufügen eines Alias

Benutzung des Sprachenfilters

  1. Hinzufügen von Modalen
  2. Hinzufügen von Verknüpfungen
  3. Hinzufügen der Freigabe/Sperrung von Elementen
  4. Hinzufügen von Sortierungen
  5. Hinzufügen von Ebenen
  6. Hinzufügen von Versionen
  7. Hinzufügen von Schlagwörtern (Tags)
  8. Hinzufügen von Zugriffsebenen
  9. Hinzufügen von Stapelverarbeitungen
  10. Hinzufügen eines Cache-Speichers
  11. Hinzufügen eines Feeds

Hinzufügen eines Aktualisierungs-Servers

  1. Adding Custom Fields
  2. Upgrading to Joomla4



Dies ist eine Artikel-Serie mit Tutorials über die Entwicklung einer Modal-View-Controller Komponente für Joomla! VersionJoomla 3.x.

Beginne mit der Einführung und navigiere durch die Artikel dieser Serie mit Hilfe des Buttons am Ende der Seite oder der Box auf der rechten Seite ("Artikel in dieser Serie").



Dieses Tutorial ist ein Teil der Entwicklung einer MVC Komponente für Joomla! 3.2 Artikel-Serie. Es ist sehr sinnvoll die vorherigen Teile des Tutorials zu lesen, bevor du hier fortfährst. In diesem Schritt fügen wir ein Modal hinzu, ein Begleitvideo ist unter Adding a Modal verfügbar.

Einführung

Modale, oder modale Fenster, sind ähnlich wie die Popup-Fenster, die an verschiedenen Stellen in Joomla! erscheinen. Beispiele sind:

  • Wenn du als Administrator ein neues Menüelement erstellst und als Menüelementtyp Beiträge / Einzelartikel auswählst, wird beim Klicken auf den Artikel ein Popup angezeigt, in dem die Details der verfügbaren Artikel angezeigt werden und du einen auswählen kannst.
  • Wenn du das Modul Administrator - Mehrsprachigkeitsstatus aktiviert hast, um deine Website im vorherigen Schritt mehrsprachig zu gestalten, und wenn du auf die Schaltfläche "Mehrsprachiger Status" links unten auf jeder Administratorseite klickst, erscheint ein Popup-Fenster, welches den Status der Mehrsprachigkeitsfunktion auf deiner Website anzeigt.

Natürlich sind diese Modals keine wirklichen Browser-Popup-Fenster - Benutzer deaktivieren diese häufig - sie verwenden stattdessen CSS und Javascript, um das Erscheinen von Pop-Ups zu imitieren. Joomla! verwendet derzeit das Framework Bootstrap Modal. Die HTML-Elemente, die das Modal einschließen, befinden sich bereits im HTML-Code der Seite, sind jedoch verborgen. Wenn Sie auf eine entsprechende Schaltfläche klicken (z. B. die Schaltfläche "Auswählen", um einen Beitrag wie im ersten Beispiel oben auszuwählen), führt der Javascript-Code nach einem Klick auf die Schaltfläche Folgendes aus:

  • die versteckten HTML-Elemente des Modals werden sichtbar gemacht
  • ein neues div-Element wird erstellt, welches das gesamte Browserfenster abdeckt; Dieser Hintergrund ist schwarz eingefärbt und hat teilweise Deckkraft, sodass das es so scheint, als wären die Elemente hinter dem Modal ausgegraut.
  • in der CSS-Datei wird der Z-Index so definiert, dass das Modal über dem Hintergrund erscheint.

Wenn du das Modal schließt, indem du z. B. einen Artikel auswählst oder auf die Schaltfläche "Schließen" klickst, werden die HTML-Elemente des Modals erneut ausgeblendet, das Hintergrund-Div entfernt und jedes von dir ausgewählte Element durch Javascript an das entsprechende Feld im Hauptformular weitergeleitet.

Jedes Modal besteht aus drei Teilen:

  • eine modale Kopfzeile oben, normalerweise mit dem Titel und der Schaltfläche X, um das Modal zu schließen,
  • ein Modalkörper, in dem die Hauptinformation erscheint, und
  • eine Modal-Fußzeile, mit Schaltflächen wie, je nach Kontext, Schließen, Speichern usw.

Allgemein gesagt, repräsentiert den Modalkörper ein Inlineframe-Element, welches eine eingebettete HTML-Seite innerhalb der Gesamtseite darstellt. HTTP-Anforderungen können erstellt werden, um anzuzeigende Daten im iframe Daten abzurufen, zu filtern, zu sortieren usw.

Funktionsweise

Derzeit haben wir in unserer hallo Welt-Komponente die Möglichkeit, einen neuen Menüpunkt mit einem Menüelementtyp "Hallo Welt" zu erstellen, der eine einzige hallo Welt-Nachricht auf unserer Website anzeigt. Bei der Auswahl der anzuzeigenden Nachricht haben wir jedoch nur ein einfaches Listenfeld, und wir müssen die Liste der Oberpunkte nach unten scrollen, um das Geeignete auszuwählen.

In diesem Schritt ändern wir die Benutzeroberfläche so, dass dem Administrator bei Auswahl der hallo Welt-Nachricht für einen neuen Menüpunkt ein Modal mit allen Details der hallo Welt-Datensätze angezeigt wird, ähnlich dem, was angezeigt wird, wenn der Administrator auf Komponenten / Hallo Welt klickt. Auf diese Weise wird dem Administrator eine viel schönere Benutzeroberfläche mit Sortier-, Such- und Filterfunktionen angezeigt.

Vorgehensweise

Die Definition dessen, was angezeigt wird, wenn ein Administrator einen Menüpunkt vom Typ Hallo Welt auswählt, ist in der XML-Datei der Seite Hallo Welt-Layoutdatei geregelt, z. B. Seite/Ansichten/hallowelt/tmpl/default.xml. Wir müssen die Felddefinition in dieser Datei zu einem benutzerdefinierten Feldtyp ändern, den wir modal_helloworld nennen.

Wir müssen Joomla! den Code für unser benutzerdefiniertes Feld zur Verfügung stellen, und wir stellen eine neue Datei bereit, um die HTML-Datei zu generieren, um unser benutzerdefiniertes Eingabefeld anzuzeigen.

Schließlich müssen wir die Anzeige der hallo Welt-Datensätze in unserem Modal überdenken. Wir werden eine Anzeige verwenden, die derjenigen ähnelt, die dem Administrator angezeigt wird, wenn er zu Komponenten / Hallo Welt navigiert, wir werden also unsere Hallo Welt-Ansicht wiederverwenden, erstellen jedoch eine neue Layoutdatei anstelle unserer derzeitigen Admindatei Ansichten/hallowelt/tmpl/default.php.

Definition eines hallo welt Menüpunkts

Wir ändern das benutzerdefinierte Feld zur Auswahl des anzuzeigenden Hallo Welt-Datensatzes.

site/views/helloworld/tmpl/default.xml

<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_HELLOWORLD_HELLOWORLD_VIEW_DEFAULT_TITLE">
		<message>COM_HELLOWORLD_HELLOWORLD_VIEW_DEFAULT_DESC</message>
	</layout>
	<fields
			name="request"
			addfieldpath="/administrator/components/com_helloworld/models/fields"
			>
		<fieldset name="request">
			<field
					name="id"
					type="modal_helloworld"
					required="true"
					label="COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_LABEL"
					description="COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_DESC"
					/>
		</fieldset>
	</fields>
</metadata>

Felddefinition

The field definition for our new custom field goes into the admin/models/fields directory. Because the field type is called modal_helloworld, with an underscore in between, Joomla will look in a /modal subdirectory for a file helloworld.php. Hence our new custom field is defined in

admin/models/fields/modal/helloworld.php

<?php

defined('JPATH_BASE') or die;

/**
 * Supports a modal for selecting a helloworld record
 *
 */
class JFormFieldModal_Helloworld extends JFormField
{
	/**
	 * Method to get the html for the input field.
	 *
	 * @return  string  The field input html.
	 */
	protected function getInput()
	{
		// Load language
		JFactory::getLanguage()->load('com_helloworld', JPATH_ADMINISTRATOR);

		// $this->value is set if there's a default id specified in the xml file
		$value = (int) $this->value > 0 ? (int) $this->value : '';
        
		// $this->id will be jform_request_xxx where xxx is the name of the field in the xml file
		$modalId = 'Helloworld_' . $this->id;

		// Add the modal field script to the document head.
		JHtml::_('jquery.framework');
		JHtml::_('script', 'system/modal-fields.js', array('version' => 'auto', 'relative' => true));

		// our callback function from the modal to the main window:
		JFactory::getDocument()->addScriptDeclaration("
			function jSelectHelloworld_" . $this->id . "(id, title, catid, object, url, language) {
				window.processModalSelect('Helloworld', '" . $this->id . "', id, title, catid, object, url, language);
			}
			");

		// if a default id is set, then get the corresponding greeting to display it
		if ($value)
		{
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('greeting'))
				->from($db->quoteName('#__helloworld'))
				->where($db->quoteName('id') . ' = ' . (int) $value);
			$db->setQuery($query);

			try
			{
				$title = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				JError::raiseWarning(500, $e->getMessage());
			}
		}
        
		// display the default greeting or "Select" if no default specified
		$title = empty($title) ? JText::_('COM_HELLOWORLD_MENUITEM_SELECT_HELLOWORLD') : htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
		$html  = '<span class="input-append">';
		$html .= '<input class="input-medium" id="' . $this->id . '_name" type="text" value="' . $title . '" disabled="disabled" size="35" />';

		// html for the Select button
		$html .= '<a'
			. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
			. ' id="' . $this->id . '_select"'
			. ' data-toggle="modal"'
			. ' role="button"'
			. ' href="#ModalSelect' . $modalId . '"'
			. ' title="' . JHtml::tooltipText('COM_HELLOWORLD_MENUITEM_SELECT_BUTTON_TOOLTIP') . '">'
			. '<span class="icon-file" aria-hidden="true"></span> ' . JText::_('JSELECT')
			. '</a>';

		// html for the Clear button
		$html .= '<a'
			. ' class="btn' . ($value ? '' : ' hidden') . '"'
			. ' id="' . $this->id . '_clear"'
			. ' href="#"'
			. ' onclick="window.processModalParent(\'' . $this->id . '\'); return false;">'
			. '<span class="icon-remove" aria-hidden="true"></span>' . JText::_('JCLEAR')
			. '</a>';

		$html .= '</span>';

		// url for the iframe
		$linkHelloworlds = 'index.php?option=com_helloworld&amp;view=helloworlds&amp;layout=modal&amp;tmpl=component&amp;' . JSession::getFormToken() . '=1';
		$urlSelect = $linkHelloworlds . '&amp;function=jSelectHelloworld_' . $this->id;
        
		// title to go in the modal header
		$modalTitle    = JText::_('COM_HELLOWORLD_MENUITEM_SELECT_MODAL_TITLE');
        
		// html to set up the modal iframe
		$html .= JHtml::_(
			'bootstrap.renderModal',
			'ModalSelect' . $modalId,
			array(
				'title'       => $modalTitle,
				'url'         => $urlSelect,
				'height'      => '400px',
				'width'       => '800px',
				'bodyHeight'  => '70',
				'modalWidth'  => '80',
				'footer'      => '<a role="button" class="btn" data-dismiss="modal" aria-hidden="true">' . JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</a>',
			)
		);

		// class='required' for client side validation.
		$class = $this->required ? ' class="required modal-value"' : '';

		// hidden input field to store the helloworld record id
		$html .= '<input type="hidden" id="' . $this->id . '_id" ' . $class 
			. ' data-required="' . (int) $this->required . '" name="' . $this->name
			. '" data-text="' . htmlspecialchars(JText::_('COM_HELLOWORLD_MENUITEM_SELECT_HELLOWORLD', true), ENT_COMPAT, 'UTF-8') 
			. '" value="' . $value . '" />';

		return $html;
	}

	/**
	 * Method to get the html for the label field.
	 *
	 * @return  string  The field label html.
	 */
	protected function getLabel()
	{
		return str_replace($this->id, $this->id . '_id', parent::getLabel());
	}
}

When the field definition class extends JFormField, Joomla expects 2 methods to be present in the class: getInput() which should return the html for the input field elements and getLabel() which should return the html for the label.

There are several core Joomla components which use modal fields to allow the administrator to select items, including com_content and com_contact. These components have similar field definitions, and the file above is a cut-down version of these equivalents, just supporting the functionality which we need for this tutorial step.

There are a number of key html input elements returned by the getInput() method above.

  1. The input field which displays the current greeting selected, or the text "Select" if none has been selected
  2. The Select button - this appears if no greeting has been selected. Note the attribute data-toggle="modal" indicating that clicking on this button will cause the modal to appear
  3. The Clear button - this appears if a greeting has been selected. When clicked it runs a javascript function within the system/modal-fields.js code which replaces the selected greeting the "Select" text, makes visible the Select button, and hides the Clear button
  4. The modal elements - these are output through including sections of the Bootstrap html and javascript code. When the modal appears the iframe is created and populated through an HTTP GET to the URL in $urlSelect.
  5. A hidden field which stores the id of the helloworld record selected, and which will be used to pass it in the HTTP POST parameters when the form is submitted.

In our case the callback function will be called jSelectHelloworld_jform_request_id, and this is the function we want to be called from the modal to pass the id and greeting of the selected helloworld record. Knowing this, window.processModalSelect will set the input fields for the greeting and id, and set the visibility of the Select and Clear buttons.

The modal knows that this is the name of the function to call because it's passed as the &function=jSelectHelloworld_jform_request_id parameter within the URL of the iframe.

Note also the &tmpl=component parameter in the URL. This means that the component.php file within the directory of the installed template will be used, which presents an html page without the Joomla menus, etc.

Modal Display

For the modal display we use the same MVC as the admin "helloworlds" functionality. Neither the controller nor model require changing, there is a small change to the view file, and there's a new layout file, which is similar to the default.php layout file, but differs in some important respects.

In the view file, we don't display the toolbar buttons nor the sidebar to choose between Messages and Categories (and some old comments have been removed as well).

admin/views/helloworlds/view.html.php

<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_helloworld
 *
 * @copyright   Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

// No direct access to this file
defined('_JEXEC') or die('Restricted access');

/**
 * HelloWorlds View
 *
 * @since  0.0.1
 */
class HelloWorldViewHelloWorlds extends JViewLegacy
{
	/**
	 * Display the Hello World view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	function display($tpl = null)
	{
		// Get application
		$app = JFactory::getApplication();
		$context = "helloworld.list.admin.helloworld";
		// Get data from the model
		$this->items			= $this->get('Items');
		$this->pagination		= $this->get('Pagination');
		$this->state			= $this->get('State');
		$this->filterForm    	= $this->get('FilterForm');
		$this->activeFilters 	= $this->get('ActiveFilters');
        
		// What Access Permissions does this user have? What can (s)he do?
		$this->canDo = JHelperContent::getActions('com_helloworld');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode('<br />', $errors));

			return false;
		}
        
		// Set the sidebar submenu and toolbar, but not on the modal window
		if ($this->getLayout() !== 'modal')
		{
			HelloWorldHelper::addSubmenu('helloworlds');
			$this->addToolBar();
		}

		// Display the template
		parent::display($tpl);

		// Set the document
		$this->setDocument();
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolBar()
	{
		$title = JText::_('COM_HELLOWORLD_MANAGER_HELLOWORLDS');

		if ($this->pagination->total)
		{
			$title .= "<span style='font-size: 0.5em; vertical-align: middle;'>(" . $this->pagination->total . ")</span>";
		}

		JToolBarHelper::title($title, 'helloworld');
		if ($this->canDo->get('core.create')) 
		{
			JToolBarHelper::addNew('helloworld.add', 'JTOOLBAR_NEW');
		}
		if ($this->canDo->get('core.edit')) 
		{
			JToolBarHelper::editList('helloworld.edit', 'JTOOLBAR_EDIT');
		}
		if ($this->canDo->get('core.delete')) 
		{
			JToolBarHelper::deleteList('', 'helloworlds.delete', 'JTOOLBAR_DELETE');
		}
		if ($this->canDo->get('core.admin')) 
		{
			JToolBarHelper::divider();
			JToolBarHelper::preferences('com_helloworld');
		}
	}
	/**
	 * Method to set up the document properties
	 *
	 * @return void
	 */
	protected function setDocument() 
	{
		$document = JFactory::getDocument();
		$document->setTitle(JText::_('COM_HELLOWORLD_ADMINISTRATION'));
	}
}

Our new modal layout file:

admin/views/helloworlds/tmpl/modal.php

<?php
/**
 * Layout file for the admin modal display of helloworld records
 *
 */

defined('_JEXEC') or die('Restricted Access');

use Joomla\Registry\Registry;

JHtml::_('behavior.core');
JHtml::_('script', 'com_helloworld/admin-helloworlds-modal.js', array('version' => 'auto', 'relative' => true));

$listOrder     = $this->escape($this->state->get('list.ordering'));
$listDirn      = $this->escape($this->state->get('list.direction'));

$app = JFactory::getApplication();
$function  = $app->input->getCmd('function', 'jSelectHelloworld');
$onclick   = $this->escape($function);
?>
<div class="container-popup">
    
<form action="<?php echo JRoute::_('index.php?option=com_helloworld&view=helloworlds&layout=modal&tmpl=component&function=' . $function . '&' . JSession::getFormToken() . '=1'); ?>" method="post" name="adminForm" id="adminForm" class="form-inline">

	<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>
    
    <div class="clearfix"></div>

        <table class="table table-striped table-hover">
            <thead>
            <tr>
                <th width="3%"><?php echo JText::_('COM_HELLOWORLD_NUM'); ?></th>
                <th width="15%">
                    <?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_HELLOWORLDS_NAME', 'greeting', $listDirn, $listOrder); ?>
                </th>
                <th width="15%">
                    <?php echo JText::_('COM_HELLOWORLD_HELLOWORLDS_POSITION'); ?>
                </th>
                <th width="15%">
                    <?php echo JText::_('COM_HELLOWORLD_HELLOWORLDS_IMAGE'); ?>
                </th>
                <th width="15%">
                    <?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_AUTHOR', 'author', $listDirn, $listOrder); ?>
                </th>
                <th width="15%">
                    <?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_LANGUAGE', 'language', $listDirn, $listOrder); ?>
                </th>
                <th width="15%">
                    <?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_CREATED_DATE', 'created', $listDirn, $listOrder); ?>
                    </th>
                <th width="5%">
                    <?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_PUBLISHED', 'published', $listDirn, $listOrder); ?>
                </th>
                <th width="2%">
                    <?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_ID', 'id', $listDirn, $listOrder); ?>
                </th>
            </tr>
            </thead>
            <tfoot>
                <tr>
                    <td colspan="5">
                        <?php echo $this->pagination->getListFooter(); ?>
                    </td>
                </tr>
            </tfoot>
            <tbody>
                <?php if (!empty($this->items)) : ?>
                    <?php foreach ($this->items as $i => $row) :
                        $row->image = new Registry;
                        $row->image->loadString($row->imageInfo);
                        if ($row->language && JLanguageMultilang::isEnabled())
                        {
                            $tag = strlen($row->language);
                            if ($tag == 5)
                            {
                                $lang = substr($row->language, 0, 2);
                            }
                            elseif ($tag == 6)
                            {
                                $lang = substr($row->language, 0, 3);
                            }
                            else {
                                $lang = '';
                            }
                        }
                        elseif (!JLanguageMultilang::isEnabled())
                        {
                            $lang = '';
                        }
                    ?>
                        <tr>
                            <td><?php echo $this->pagination->getRowOffset($i); ?></td>
                            <td>
                                <?php 
                                $link = 'index.php?option=com_helloworld&view=helloworld&id=' . $row->id;
                                $attribs = 'data-function="' . $this->escape($onclick) . '"'
								. ' data-id="' . $row->id . '"'
								. ' data-title="' . $this->escape(addslashes($row->greeting)) . '"'
								. ' data-uri="' . $link . '"'
								. ' data-language="' . $this->escape($lang) . '"'
                                ;
                                ?>
                                <a class="select-link" href="javascript:void(0)" <?php echo $attribs; ?>>
                                    <?php echo $this->escape($row->greeting); ?>
                                </a>
                                <span class="small break-word">
                                	<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($row->alias)); ?>
                                </span>
                                <div class="small">
									<?php echo JText::_('JCATEGORY') . ': ' . $this->escape($row->category_title); ?>
								</div>
                            </td>
                            <td align="center">
                                <?php echo "[" . $row->latitude . ", " . $row->longitude . "]"; ?>
                            </td>
                            <td align="center">
                                <?php
                                    $caption = $row->image->get('caption') ? : '' ;
                                    $src = JURI::root() . ($row->image->get('image') ? : '' );
                                    $html = '<p class="hasTooltip" style="display: inline-block" data-html="true" data-toggle="tooltip" data-placement="right" title="<img width=\'100px\' height=\'100px\' src=\'%s\'>">%s</p>';
                                    echo sprintf($html, $src, $caption);  ?>
                            </td>
                            <td align="center">
                                <?php echo $row->author; ?>
                            </td>
                            <td align="center">
                                <?php echo JLayoutHelper::render('joomla.content.language', $row); ?>
                            </td>
                            <td align="center">
                                <?php echo substr($row->created, 0, 10); ?>
                            </td>
                            <td align="center">
                                <?php echo JHtml::_('jgrid.published', $row->published, $i, 'helloworlds.', true, 'cb'); ?>
                            </td>
                            <td align="center">
                                <?php echo $row->id; ?>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                <?php endif; ?>
            </tbody>
        </table>
        <input type="hidden" name="task" value=""/>
        <input type="hidden" name="boxchecked" value="0"/>
        <?php echo JHtml::_('form.token'); ?>
</form>
</div>

Note that there are some important differences from the default.php layout file.

  1. We get the function parameter which is embedded in the iframe URL as a query parameter, and we use this in the URL target of the <form> element and in the data-function attribute of the each greeting value.
  2. There are several other data attributes associated with each greeting value; these will be used to pass this information to the parent window via the jSelectHelloworld_jform_request_id function call. Also, each greeting has a CSS class of "select-link".
  3. We need to set the target URL of the <form> to be the same as the URL of the iframe. This is because whenever the administrator uses the search / filter tools the form sends an HTTP request to that URL, and we need to ensure it's the same data that gets presented.

Also, the checkboxes have been removed, as they are now irrelevant.

In addition, we need a small javascript file which basically sets an onclick listener on each of the greetings (identified through having the class "select-link"), and calls the required function when triggered.

media/js/admin-helloworlds-modal.js

(function() {
	"use strict";
	/**
	 * Javascript to set up onclick listeners on the helloworld greetings
	 * When a greeting is clicked the listener invokes the function in the parent window
	 * which is given by the data-function attribute of the helloworld greeting html element
	 * In this way the identity of the helloworld record selected in the modal is passed to the field in the parent window
	 */

	document.addEventListener('DOMContentLoaded', function(){
		
		var elements = document.querySelectorAll('.select-link');

		for(var i = 0, l = elements.length; l>i; i++) {
			
			elements[i].addEventListener('click', function (event) {
				event.preventDefault();
				var functionName = event.target.getAttribute('data-function');
				window.parent[functionName](event.target.getAttribute('data-id'), event.target.getAttribute('data-title'), null, null, event.target.getAttribute('data-uri'), event.target.getAttribute('data-language'), null);
			})
		}
	});
})();

Updated Language Strings

admin/language/en-GB/en-GB.com_helloworld.ini

; Joomla! Project
; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
; Note : All ini files need to be saved as UTF-8

COM_HELLOWORLD_ADMINISTRATION="HelloWorld - Administration"
COM_HELLOWORLD_ADMINISTRATION_CATEGORIES="HelloWorld - Categories"
COM_HELLOWORLD_NUM="#"
COM_HELLOWORLD_HELLOWORLDS_FILTER="Filters"
COM_HELLOWORLD_AUTHOR="Author"
COM_HELLOWORLD_LANGUAGE="Language"
COM_HELLOWORLD_CREATED_DATE="Created"
COM_HELLOWORLD_PUBLISHED="Published"
COM_HELLOWORLD_HELLOWORLDS_NAME="Name"
COM_HELLOWORLD_HELLOWORLDS_POSITION="Position"
COM_HELLOWORLD_HELLOWORLDS_IMAGE="Image"
COM_HELLOWORLD_ID="Id"

COM_HELLOWORLD_HELLOWORLD_CREATING="HelloWorld - Creating"
COM_HELLOWORLD_HELLOWORLD_DETAILS="Details"
COM_HELLOWORLD_HELLOWORLD_EDITING="HelloWorld - Editing"
COM_HELLOWORLD_HELLOWORLD_ERROR_UNACCEPTABLE="Some values are unacceptable"
COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_DESC="The category the messages belongs to"
COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_LABEL="Category"
COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_DESC="This message will be displayed"
COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_LABEL="Message"
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL="Show category"
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC="If set to Show, the title of the message&rsquo;s category will show."
COM_HELLOWORLD_HELLOWORLD_FIELD_LATITUDE_LABEL="Latitude"
COM_HELLOWORLD_HELLOWORLD_FIELD_LATITUDE_DESC="Enter the position latitude, between -90 and +90 degrees"
COM_HELLOWORLD_HELLOWORLD_FIELD_LONGITUDE_LABEL="Longitude"
COM_HELLOWORLD_HELLOWORLD_FIELD_LONGITUDE_DESC="Enter the position longitude, between -180 and +180 degrees"
COM_HELLOWORLD_HELLOWORLD_FIELD_LANGUAGE_DESC="Select the appropriate language"
COM_HELLOWORLD_IMAGE_FIELDS="Image details"
COM_HELLOWORLD_HELLOWORLD_FIELD_IMAGE_LABEL="Select image"
COM_HELLOWORLD_HELLOWORLD_FIELD_IMAGE_DESC="Select an image from the library, or upload a new one"
COM_HELLOWORLD_HELLOWORLD_FIELD_ALT_LABEL="Alt text"
COM_HELLOWORLD_HELLOWORLD_FIELD_ALT_DESC="Alternative text (if image cannot be displayed)"
COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTION_LABEL="Caption"
COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTION_DESC="Provide a caption for the image"
COM_HELLOWORLD_HELLOWORLD_HEADING_GREETING="Greeting"
COM_HELLOWORLD_HELLOWORLD_HEADING_ID="Id"
COM_HELLOWORLD_MANAGER_HELLOWORLD_EDIT="HelloWorld manager: Edit Message"
COM_HELLOWORLD_MANAGER_HELLOWORLD_NEW="HelloWorld manager: New Message"
COM_HELLOWORLD_MANAGER_HELLOWORLDS="HelloWorld manager"
COM_HELLOWORLD_EDIT_HELLOWORLD="Edit message"
COM_HELLOWORLD_N_ITEMS_DELETED_1="One message deleted"
COM_HELLOWORLD_N_ITEMS_DELETED_MORE="%d messages deleted"
COM_HELLOWORLD_N_ITEMS_PUBLISHED="%d message(s) published"
COM_HELLOWORLD_N_ITEMS_UNPUBLISHED="%d message(s) unpublished"
COM_HELLOWORLD_HELLOWORLD_GREETING_LABEL="Greeting"
COM_HELLOWORLD_HELLOWORLD_GREETING_DESC="Add Hello World Greeting"
COM_HELLOWORLD_SUBMENU_MESSAGES="Messages"
COM_HELLOWORLD_SUBMENU_CATEGORIES="Categories"
COM_HELLOWORLD_CONFIGURATION="HelloWorld Configuration"
COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_LABEL="Messages settings"
COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_DESC="Settings that will be applied to all messages by default"
COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTCHA_LABEL="Captcha"
COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTCHA_DESC="Select Captcha to use on front end form"
COM_HELLOWORLD_HELLOWORLD_FIELD_USER_TO_EMAIL_LABEL="User to email"
COM_HELLOWORLD_HELLOWORLD_FIELD_USER_TO_EMAIL_DESC="Select user to email when a new message is entered on front end"
COM_HELLOWORLD_FIELDSET_RULES="Message Permissions"
COM_HELLOWORLD_FIELD_RULES_LABEL="Permissions"
COM_HELLOWORLD_ACCESS_DELETE_DESC="Is this group allowed to edit this message?"
COM_HELLOWORLD_ACCESS_DELETE_DESC="Is this group allowed to delete this message?"
COM_HELLOWORLD_TAB_NEW_MESSAGE="New Message"
COM_HELLOWORLD_TAB_EDIT_MESSAGE="Message Details"
COM_HELLOWORLD_TAB_PARAMS="Parameters"
COM_HELLOWORLD_TAB_PERMISSIONS="Permissions"
COM_HELLOWORLD_TAB_IMAGE="Image"
COM_HELLOWORLD_LEGEND_DETAILS="Message Details"
COM_HELLOWORLD_LEGEND_PARAMS="Message Parameters"
COM_HELLOWORLD_LEGEND_PERMISSIONS="Message Permissions"
COM_HELLOWORLD_LEGEND_IMAGE="Image info"
; Column ordering in the Helloworlds view
COM_HELLOWORLD_ORDERING_ASC="Greeting ascending"
COM_HELLOWORLD_ORDERING_DESC="Greeting descending"
COM_HELLOWORLD_AUTHOR_ASC="Author ascending"
COM_HELLOWORLD_AUTHOR_DESC="Author descending"
COM_HELLOWORLD_CREATED_ASC="Creation date ascending"
COM_HELLOWORLD_CREATED_DESC="Creation date descending"
COM_HELLOWORLD_PUBLISHED_ASC="Unpublished first"
COM_HELLOWORLD_PUBLISHED_DESC="Published first"
COM_HELLOWORLD_LANGUAGE_ASC="Language ascending"
COM_HELLOWORLD_LANGUAGE_DESC="Language descending"
; Helloworld menuitem - selecting a greeting via modal
COM_HELLOWORLD_MENUITEM_SELECT_MODAL_TITLE="Select greeting"
COM_HELLOWORLD_MENUITEM_SELECT_HELLOWORLD="Select"
COM_HELLOWORLD_MENUITEM_SELECT_BUTTON_TOOLTIP="Select a helloworld greeting"

Packaging the Component

Contents of your code directory. Each file link below takes you to the step in the tutorial which has the latest version of that source code file.

helloworld.xml

<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.0" method="upgrade">

	<name>COM_HELLOWORLD</name>
	<!-- The following elements are optional and free of formatting constraints -->
	<creationDate>January 2018</creationDate>
	<author>John Doe</author>
	<authorEmail>john.doe@example.org</authorEmail>
	<authorUrl>http://www.example.org</authorUrl>
	<copyright>Copyright Info</copyright>
	<license>License Info</license>
	<!--  The version string is recorded in the components table -->
	<version>0.0.22</version>
	<!-- The description is optional and defaults to the name -->
	<description>COM_HELLOWORLD_DESCRIPTION</description>

	<!-- Runs on install/uninstall/update; New in 2.5 -->
	<scriptfile>script.php</scriptfile>

	<install> <!-- Runs on install -->
		<sql>
			<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
		</sql>
	</install>
	<uninstall> <!-- Runs on uninstall -->
		<sql>
			<file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
		</sql>
	</uninstall>
	<update> <!-- Runs on update; New since J2.5 -->
		<schemas>
			<schemapath type="mysql">sql/updates/mysql</schemapath>
		</schemas>
	</update>

	<!-- Site Main File Copy Section -->
	<!-- Note the folder attribute: This attribute describes the folder
		to copy FROM in the package to install therefore files copied
		in this section are copied from /site/ in the package -->
	<files folder="site">
		<filename>index.html</filename>
		<filename>helloworld.php</filename>
		<filename>controller.php</filename>
		<filename>router.php</filename>
		<folder>controllers</folder>
		<folder>views</folder>
		<folder>models</folder>
		<folder>helpers</folder>
	</files>

		<languages folder="site/language">
			<language tag="en-GB">en-GB/en-GB.com_helloworld.ini</language>
			<language tag="fr-FR">fr-FR/fr-FR.com_helloworld.ini</language>
		</languages>

	<media destination="com_helloworld" folder="media">
		<filename>index.html</filename>
		<folder>images</folder>
		<folder>js</folder>
		<folder>css</folder>
	</media>

	<administration>
		<!-- Administration Menu Section -->
		<menu link='index.php?option=com_helloworld' img="../media/com_helloworld/images/tux-16x16.png">COM_HELLOWORLD_MENU</menu>
		<!-- Administration Main File Copy Section -->
		<!-- Note the folder attribute: This attribute describes the folder
			to copy FROM in the package to install therefore files copied
			in this section are copied from /admin/ in the package -->
		<files folder="admin">
			<!-- Admin Main File Copy Section -->
			<filename>index.html</filename>
			<filename>config.xml</filename>
			<filename>helloworld.php</filename>
			<filename>controller.php</filename>
			<filename>access.xml</filename>
			<!-- SQL files section -->
			<folder>sql</folder>
			<!-- tables files section -->
			<folder>tables</folder>
			<!-- models files section -->
			<folder>models</folder>
			<!-- views files section -->
			<folder>views</folder>
			<!-- controllers files section -->
			<folder>controllers</folder>
			<!-- helpers files section -->
			<folder>helpers</folder>
		</files>
		<languages folder="admin/language">
			<language tag="en-GB">en-GB/en-GB.com_helloworld.ini</language>
			<language tag="en-GB">en-GB/en-GB.com_helloworld.sys.ini</language>
			<language tag="fr-FR">fr-FR/fr-FR.com_helloworld.ini</language>
			<language tag="fr-FR">fr-FR/fr-FR.com_helloworld.sys.ini</language>
		</languages>
	</administration>

</extension>

Contributors