在前面也谈过一篇关于joomla中自定义表单字段的文章。自己重头读一次,连自己都晕了。当时只是简单的翻译了一下官网的文章,以为真的懂了,真正用的时候才知道差远了。本节将继续讨论这个话题,如何自定义表单字段。
在自己开发的下载组件中,写了两个视图,一个是项目列表视图,一个是项目详情视图。当时就在项目列表目录下加了一个default.xml。能够产生一个项目列表的菜单链接。现在我需要单独的新建一个i菜单项,让该菜单项指向一个具体的下载项目。
这 个需求,实现起来感觉很简单。但有一个问题我们必须解决。如何实现让用户向选择单篇文章一样选择一个下载项目呢?因为以前有过类似的经验,大体知道思考的 方向应该是如何自定以表单字段了。查看了一下系统核心的文章组件的实现方法,大概理解了自定义表单字段的操作原理和步骤了。
因为需要能产生菜单类型,所以我们需要在视图中增加一个.xml文件。一个典型的.xml文件如下:
<metadata> <layout title="COM_DOWNLOAD_VIEW_ITEMDETAIL_TITLE" option="COM_DOWNLOAD_VIEW_ITEMDETAIL_DEFAULT_OPTION"> <message> COM_DOWNLOAD_VIEW_ITEMDETAIL_DESC </message> </layout> <fields name="request"> <fieldset name="request" addfieldpath="/administrator/components/com_download/models/fields" > <field name="id" type="item" label="选择一个项目" required="true" description="请选择一个项目" /> </fieldset> </fields> <!-- Add fields to the parameters object for the layout--> <fields name="params"> <!-- Basic options --> <fieldset name="basic" label="基本参数" > <field name="show_title" type="list" label="显示标题" description="显示标题" > <option value="">依据全局设置</option> <option value="0">隐藏</option> <option value="1">显示</option> </field> </fieldset> </fields> </metadata>
前面的一部分是菜单类型的描述信息,后一部分是该菜单类型关联的参数。在上面中我们给该菜单类型关联了两个参数。一个是用来确定该菜单指向那一个项目,这个是必须的。另外一个是控制是否显示标题的选项。
于2014-06-24日改:我们需要注意fields和fieldset的描述,这两个字段中都指定了name=request。这就是在告诉菜单项我们应该将这个变量和这个变量的值加入到URL中
重 点关注field的type属性。第一个是type=item.第二个是type=list.系统中预定义了很多常规的的type,比喻现在的 type=list就是一个系统类型。而type=item则是我们自定的表单的类型。因为是自定义,所以我们需要指明定义这个type的实现文件在什么 地方。一般我们通过fieldset的addincludepath属性来指定。在上面的代码中我们说明了type=item这个类型的定义可以在 /administrator/components/com_download/models/fields这个目录下找到。
更加直接一点,系统预计会在/administrator/components/com_download/models/fields 文件夹中找到item.php这个文件。并且在item.php文件中找到JFormFieldItem这个类的定义。
我们需要实现的效果如下:
点击按钮之后就会弹出一个对话框让我们选择一个下载项目,当我们选择完下载项目之后就关闭这个对话框。一切都那么的熟悉!其实就是系统的文章组件关联一篇文章的操作。
大体的逻辑应该是这样:
点击按钮,系统弹出一个i模态对话框(这个工作我们在前几章已经做过)。在这个模态对话框中显示一个视图,这个视图展示所有的下载项目列表。点击其中一项后关闭模态对话框,设置参数项。
在上面的逻辑中,如何弹出一个模态对话框,这个应该可以解决。如何在模态对话框中显示一个视图也很容易解决。最难的一部分就是如何将模态对话框中的选择表现到我们自定义的字段上。joomla实现这个是通过js来实现的。
看一下item.php的具体代码:
<?php defined('JPATH_BASE') or die; /** * Supports a modal itme picker * @package com_download */ class JFormFieldItem extends JFormField { /** * The form field type */ protected $type="Item"; /** * Method to get the field input markup. * * @return string The field input markup */ protected function getInput() { //Load the modal behavior script JHtml::_('behavior.modal' ,'a.modal'); //Build the script $script = array(); $script[] = ' function SelectItem(id ,title ,catid ){'; $script[] = ' document.id("'.$this->id.'_id").value = id;'; $script[] = ' document.id("'.$this->id.'_name").value = title;'; $script[] = ' SqueezeBox.close();'; $script[] = ' }'; // Add the script to the document head JFactory::getDocument()->addScriptDeclaration(implode("\n" ,$script)); // Setup variables for display $html = array(); $link = 'index.php?option=com_download&view=items&layout=modal&tmpl=component&function=SelectItem'; $db = JFactory::getDBO(); $db->setQuery('SELECT title FROM #__download WHERE id ='.(int)$this->value); $title = $db->loadResult(); if($error = $db->getErrorMsg()) { JError::raiseWarning(500 ,$error); } if(empty($title)) { $title = JText::_("选择一篇文章"); } $title = htmlspecialchars($title ,ENT_QUOTES ,'UTF-8'); //The current user display field $html[] = '<div class="fltlft">'; $html[] = ' <input type="text" id="'.$this->id.'_name" value="'.$title.'"disabled="disabled" size="35" />'; $html[] = '</div>'; // The user select button $html[] = '<div class="button2-left">'; $html[] = ' <div class="blank">'; $html[] = ' <a class="modal" title="选择一个项目" href="'.$link.'&'.JSession::getFormToken().'=1" rel="{handler:\'iframe\',size:{x:800 ,y:450}}" >'.JText::_('按钮').'</a>'; $html[] = ' </div>'; $html[] = '</div>'; // The active article id field if(0 == (int)($this->value)) { $value=''; } else { $value=(int)$this->value; } // Class='required' for client side validation $class=''; if($this->required) { $class= ' class="required modal-value"'; } $html[]= '<input type="hidden" id="'.$this->id.'_id"'.$class.' name="'.$this->name .'" value="'.$value.'" />'; return implode("\n" ,$html); } }
自定的表单字段应该派生自JFormField类。并且你的类名应该为JFormFieldItem。因为JFormField类 中有一个虚的方法getInput(),所以我们必须在JFormFieldItem中实现这个方法。看一下JFormField的源代码,你就明白我在 说什么了。
上面代码的逻辑很清晰。重点就在于动态加载js的那一部分。
//Build the script $script = array(); $script[] = ' function SelectItem(id ,title ,catid ){'; $script[] = ' document.id("'.$this->id.'_id").value = id;'; $script[] = ' document.id("'.$this->id.'_name").value = title;'; $script[] = ' SqueezeBox.close();'; $script[] = ' }';
在这一部分,用到了$this->id.'_id';这个我也没弄清$this->id是怎么会是。但是看一下页面源码,你就会清楚,他其实就是通过一个id来获得一个元素,然后设置该元素的值。就是这样的简单。
于2014-06-24改:$this->id= jform_request_id。jform就是我们在loadForm方法中加载的表单的名称,request就是代表这个字段是必须的。id就是这个字段的名称。并且我们在在后加上了一个隐藏的字段jform_request_id_id这个就代表了模态对话框中的选择的值。
评论 (0)