Creating a modal form field using JFormFieldModal
From Joomla! Documentation
| This page documents a feature that has been proposed, but not yet implemented in Joomla!. Therefore you cannot use this to develop a universal extension (i.e. an extension that works on all installations of Joomla). |
Contents |
Preface
This is a tutorial for classes which were proposed here: http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=20180
Therefore, if you want to not only read this tutorial but also test the examples, then don't forget to apply the patches.
Introduction
You can easily add to your application a form field which uses a modal window to receive a value. Just use one of already existing JFormFieldModal family's members or create a new class.
Test environment
In this tutorial you will be led through several usage examples, that's why you should prepare and test a test environment.
Preparing
Firstly, download and install com_jformtest. This is a component with already created and displayed form. We can easily add fields to the form. We can easily add new field types and use them in the form. So, this component will be helpful not only in this tutorial but also in your experiments with the form framework.
Here is the entry point of the component:
administrator/components/com_jformtest/jformtest.php
<?php
defined('_JEXEC') or die('Direct access only');
jimport('joomla.application.component.controller');
$ctrl = JController::getInstance('jformtest');
$ctrl->execute(JRequest::getCmd('task'));
$ctrl->redirect();
This is the controller:
administrator/components/com_jformtest/controller.php
<?php
defined('_JEXEC') or die('Direct access only');
class jformtestController extends JController {
public function display()
{
jimport('joomla.form.form');
$models_path = JPATH_COMPONENT . DS . 'models';
JForm::addFormPath ($models_path . DS . 'forms');
JForm::addFieldPath($models_path . DS . 'fields');
$form = JForm::getInstance('jformtest', 'form');
$form->bind(JRequest::get('METHOD'));
$type = JFactory::getDocument()->getType();
$this->getView($this->getName(), $type)->set('Form', $form);
parent::display();
}
}
The view:
administrator/components/com_jformtest/views/jformtest/view.html.php
<?php
defined('_JEXEC') or die('Direct access only');
jimport('joomla.application.component.view');
class jformtestViewjformtest extends JView {
public function display() {
$this->assign('form', $this->get('Form'));
parent::display();
}
}
The layout:
administrator/components/com_jformtest/views/jformtest/tmpl/default.php
<?php
defined('_JEXEC') or die('Direct access only');
?>
<table>
<form name='<?php echo $this->form->getName() ?>'>
<?php foreach($this->form->getFieldset() as $field): ?>
<tr>
<td><?php echo $field->label ?>:</td>
<td><?php echo $field->input ?></td>
</tr>
<?php endforeach ?>
<tr>
<td></td>
<td>
<input type='submit' />
<input type="hidden" name="option" value="<?php echo JRequest::getVar('option') ?>" />
</td>
</tr>
</form>
</table>
...and the form definition:
administrator/components/com_jformtest/models/forms/form.xml
<?xml version="1.0" encoding="utf-8"?>
<form name="jformtest">
<fieldset name="fields">
<field name="hello" id="hello" type="modalinternal" label="Greetings from the modal window" win_width="300" win_height="30">
<postcontent><![CDATA[
<div style='text-align: center; font-size: 18px;'>
<a href="#" onclick="activeField.insert('Hello, World'); SqueezeBox.close();">Click here to greet the world.</a>
</div>
]]>
</postcontent>
</field>
</fieldset>
</form>
Testing
- In the backend go to "Components -> jformtest". You will see this:
- Click on a button with "select" text on it. A modal window will be opened:
- Click on a link with "Click here to greet the world" text on it. The modal window will be closed and "Hello, World" text will be inserted into the input box:
If you were able to accomplish all the steps above, then you are ready to go ahead.
The JFormFieldModal family of classes
You can think about JFormFieldModal class as about family's totem. It is an abstract class and you can't use it directly, but it holds the spirit of all modal form fields. The first real classes which you can use is JFormFieldModalInternal and JFormFieldModalExternal. Of course, there can be another direct totem's descendants in the future.
JFormFieldModalInternal
This is a class for fields whose modal windows receive their content by cloning an html-block from the current page. So, content for a modal field is embedded in a page where a form field resides. With this class you don't need to prepare an application for working in popup-mode, you only need to prepare content for a modal window. This class suits best in situations when content in a modal window is mostly static. You can store content for a modal window in your form's XML-definition (ad-hoc usage) or generate content in a subclass.
Ad-hoc usage
Let's create a modal window which allows to choose one of the Joomla's logo colors. Simply open the form definition and put this into it:
administrator/components/com_jformtest/models/forms/form.xml
<?xml version="1.0" encoding="utf-8"?>
<form name="jformtest">
<fieldset name="fields">
<field name="jcolor" id="jcolor" type="modalinternal" label="Your favorite Joomla! color" win_width="300" win_height="300">
<postcontent><![CDATA[
<style type='text/css'>
.colorbox { cursor: pointer; width: 150px; height: 150px; }
</style>
<script language='javascript'>
function insertColor(colorbox)
{
activeField.insert($(colorbox).getStyle("background-color"));
SqueezeBox.close();
}
</script>
<div class='colorbox' style='float: left; background-color: green;' onclick='insertColor(this)'></div>
<div class='colorbox' style='float: right; background-color: orange;' onclick='insertColor(this)'></div>
<div style='clear: both;'></div>
<div class='colorbox' style='float: left; background-color: blue;' onclick='insertColor(this)'></div>
<div class='colorbox' style='float: right; background-color: red;' onclick='insertColor(this)'></div>
]]>
</postcontent>
</field>
</fieldset>
</form>
As you see we've specified modal window's content in the field's child element named "postcontent". Strictly speaking, "precontent" and "postcontent" field's child elements is for customizing JFormFieldModalInternal's subclasses. We will talk about this further, but now, if we can specify some content in these elements why not to use this for creating a field without need for subclassing?
After HTML-document generation the content will be placed near the form field in invisible block. That is, content of a modal window is a part of a HTML-page on which a form resides. So you should be careful to don't break form's HTML-page with field's CSS or JavaScript. Also it should be obvious that if you write this:
<postcontent><![CDATA[
alert('Hello');
]]>
</postcontent>
then you will get an alert on a form's page, not in the modal window. [1]
You perhaps want to test newly created field on your form's page:
After clicking on the "Select" button you should see this modal window:
Click on one of the colors and it's name will be placed into the form field:
You will be happy with this until you don't wish to use the form field several times or in another form. If you will wish this, then you should consider creation of a subclass.
Subclassing
JFormFieldModalExternal
This is a class for form fields whose modal windows receive their content by making another web-request. This is the choose when you need a real dynamic web-application in a modal window (with search, sorting, etc). If you want to use this class you should prepare an application for working in popup-mode or use an already ready one. You should specify a URL by which an application is executed in your form's XML-definition (ad-hoc usage) or in a subclass. In last case you can also dynamically generate it.
Ad-hoc usage
Subclassing
JFormFieldMedia subclass
Family members' similarities
JFormFieldModal provides many useful features for their descendants.
References
- ↑ Technically it's possible to specify JavaScript code as a part of modal window's content and execute it in this window. To implement this you should put modal window's content on a page after DOM-tree will be ready for use.





