A generic tabbed template for complex large Alfresco forms

cancel
Showing results for 
Search instead for 
Did you mean: 

A generic tabbed template for complex large Alfresco forms

rfernandes
Active Member
0 5 15.8K
Sometimes you may need to have considerably large and complex forms that may not show best using the Alfresco out of the box form templates. In this post I present a generic solution template and the instructions on how to use it.



The code for the tabbed form template can be found at:



http://code.google.com/p/tabbed-form/



 



It’s composed of:



  • src/main/resources/alfresco/web-extension/site-webscripts/org/alfresco/components/form/tabbed.ftl The freemarker form template itself. This file contains all the logic for the structure of the form discussed in this document.


  • src/main/resources/META-INF/css/tabbed.css The CSS stylesheet for the elements used by the form template.


  • src/main/resources/META-INF/js/tabbed.js The client side javascript with the functions used by the form template mostly for the tabbed structuring of fields.


 



How to install it



For installing it (after extracting it locally as per http://code.google.com/p/tabbed-form/source/checkout) just execute:



 

mvn clean install


 



This will generate a jar file in the target folder: tabbed-alfresco-form-1.0.0.jar



Copy it to the shared/lib folder of your tomcat install or inside the WEB-INF/lib folder of your share webapp (you can also make the jar part of your own extension amp). In the first case make sure your tomcat installation has been configured properly for loading shared libraries. In conf/catalina.properties you should have set for that:



 

shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar


 



Restart your server and you should be able to use the new form template.



 



How to use it



The form template can be used for any form. Depending on where you want to use it and what you exactly need some tweaking on original code might be required. Here we will present the example of using the form template for editing the properties of a content type but the instructions will be still valid for whatever other case of Share form you may use it.



On shared/classes/alfresco/web-extension/share-config-custom.xml add it to the custom configuration (don’t worry into understanding it exactly for now) the same sample configuration as contained in the second config tag of https://code.google.com/p/tabbed-form/source/browse/sample/share-config-custom.xml



After any editing of the shared/classes/alfresco/web-extension/share-config-custom.xml  you don't need to restart the server just go to http://localhost:8080/share/page/index and refresh the web scripts, the share application configuration should be refreshed.



Now just make sure to add for a certain document in any site the aspects:



  • Emailed


  • Effecitivity


  • Dublin Core


 



If you edit now the properties of the document you should see something like this:



 



Tabbed_Complex_Form_Template



 



If you click on Extra tab above:



Tabbed_Complex_Form_Template2



 



Now let’s discuss how our configuration of the form template before led us to get this.



About the field-visibility tag on the configuration there’s nothing much to say except to specify all fields you want to see on the form.



Then on edit-form tag we specify our template:



 

<edit-form template='tabbed.ftl' />


 



On the appearance tag is where all the logic of the form templates comes in action.



 



The tabs



First we specify our tabs we want our form to be structured. In our case we just have two:



 

               <set id='Zgeneric' label='Generic' />



               <set id='Zextra' label='Extra' />


 



Note that we use the id for both cases starting with a Z. This is important. And after on the label the name we want to show for each tab.



Tabbed_Complex_Form_Template3



 



The tab major layout



Afterwards we specify the major layout columns for each tab.



 

             <set id='generic1' parent='Zgeneric' label='' />



               <set id='extra1' parent='Zextra' label='' />



               <set id='extra2' parent='Zextra' label='' />


 



So we are specifying 1 single major layout column for the generic tab (look at the parent attribute for each set) and 2 major layout columns for the extra tab.



Tabbed_Complex_Form_Template4



 



Here the exact id given to each set is not important. It’s assumed that any primary child set of a a tab set (Zgeneric and Zextra) are always specifying the number of columns of the tab layout.



 



The Group Sets



After we specify the groups in which we want to gather the fields (they are surrounded with a blue line and the corresponding label group). This allows for more structuring on our forms.



 

               <!-- generic group -->



               <set id='Ggeneric' parent='generic1' label='Generic'/>



               <!-- dates group -->



               <set id='Gdates' parent='generic1' label='Control'/>



          <!-- dublin group -->



               <set id='Gdublin' parent='extra1' label='Dublin'/>



                <!-- emailed group -->



               <set id='Gemailed' parent='extra2' label='Emailed'/>



                <!-- effectivity group -->



               <set id='Geffectivity' parent='extra2' label='Effectivity'/>


 



So we can see that for the single column of the first Generic tab we have two group sets: Generic and Control. The id here is important and it should start by a G. The labels are also going to be used on the representation of the form. Note that the parent is always the column tab layout they belong to.



Tabbed_Complex_Form_Template5



 



For the 2 columns of the Extra tab layout we have 3 groups: Dublin, Emailed and Effectivity (corresponding to the aspects we have added to the document). The Dublin one we represent on the first column of the tab, while the other two in the second.



Tabbed_Complex_Form_Template6



 



The table like structure of group fields



For each group before we can specify a fairly complex table like structure for the distribution of the fields in order to get the best look and feel we want. In our example we just use this capability in full for the groups Generic and Control of the first Generic tab. But it should be enough for understanding the template logics for others usages.



So lets look first to the generic subgroup in the first tab:



Tabbed_Complex_Form_Template7



 

              <!-- name -->



               <set id='110Ggeneric-0-0' parent='Ggeneric'/>



               <!-- mimetype -->



               <set id='110Ggeneric-0-1' parent='Ggeneric'/>



                <!-- description -->



               <set id='121Ggeneric-0-2' parent='Ggeneric'/>



               <!-- title -->



               <set id='211Ggeneric-1-0' parent='Ggeneric'/>


 



Each one of these set tags is specifying the cell distribution (row and column span and break of lines) for the subgroup Ggeneric. This is done through the id first 3 numbers. The rest of the id just has to guarantee that the id is overall unique and we use a convention based on the subgroup name and the row and column within the row, but it is not interpreted by the form template.



  • The first number specifies the column span of the cell


  • The second number the row span of the cell


  • And the third number specifies if the row ends (1) or continues to the next cell/set (0).


 



So for 110Ggeneric-0-0 we are specifying the name cell has a row and column span 1 (so no span) and the line continues.



For the 110Ggeneric-0-1 of the mime type the same.



For 121Ggeneric-0-2 of the description we are specifying there’s no column span but there’s row span, so the cell spans to the row after. As you can check looking the form screenshot.



Finally for the title 211Ggeneric-1-0 we do the opposite, spanning the columns but not the row. As again is visible on the screen shot.



If we look into the next subgroup Control:



Tabbed_Complex_Form_Template8



 



The structure is much more simple and now we probably don’t need to explain the configuration:



 

               <!-- creator -->



               <set id='110Gdates-0-0' parent='Gdates'/>



                <!-- modifier -->



               <set id='111Gdates-0-1' parent='Gdates'/>



               <!-- created -->



               <set id='110Gdates-1-0' parent='Gdates'/>



               <!-- modified -->



               <set id='111Gdates-1-1' parent='Gdates'/>


 



For the Extra tab the table structure for each subgroup is the simplest possible with no row or column span and each cell occupying a full row. So all ids start by 111.



So far we just described the set tags that define the layout but haven't discussed the field tags yet. The fields tags are needed and through the set attribute it’s how we map each field with the set/cell it belongs to:



 

               <field id='cm:name' set='110Ggeneric-0-0'>



                   <control>



                       <control-param name='style'>width: 150px;</control-param>



                   </control>



               </field>



               <field id='mimetype'  set='110Ggeneric-0-1'>



                  <control template='/org/alfresco/components/form/controls/mimetype.ftl'>



                       <control-param name='style'>width: 200px;</control-param>



                  </control>



               </field>


 



But aside that there’s nothing particular about the field tag settings when using the tabbed.ftl form template.



HIH
5 Comments
blog_commenter
Active Member
Nice, small & useful. Thank you for sharing.
blog_commenter
Active Member
Hi,



Could it be possible to know on which Alfresco versions this template is compatible?



Regards.
blog_commenter
Active Member
Hi,



It's a really interesting project, why choose Google Code instead GitHub?

It will be more confortable to send pull requests (for example, the template doesn't work if a field is not attached to a form set (due to the default tab)) or just fork the project.



Regards.
rfernandes
Active Member
Thanks Luis.



Bertrand,

It has been used in different Enterprise versions 3.4.x, 4.1.x and even 4.2.0 preview.

If you want to be a collaborator on the Google Code project I can add you to it. Or just fork it into your own Github project.
h_john
Active Member

Hi.

You explained exactly what I need. But there no files on http://code.google.com/p/tabbed-form/source/checkout

I found some information on another site Forms Examples  but it don`t work with Alfresco 5.0.d. I made some changes in tab-edit-form.ftl.... and now I can see form, tabs I`ve created, buttons but there no fields.

Can some one help me with it?

Here is my tab-edit-form.ftl

<#import "/org/alfresco/components/form/form.lib.ftl" as formLib />
 
<!-- Dependency files for Tabview -->
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.9.0/build/tabview/assets/skins/sam/tabview.css">
<script type="text/javascript" src="http://yui.yahooapis.com/2.9.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.9.0/build/element/element-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.9.0/build/connection/connection-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.9.0/build/tabview/tabview-min.js"></script>
 
 
<#if error?exists>
   <div class="error">${error}</div>
<#elseif form?exists>
 
   <#assign formId=args.htmlid + "-form">
   <#assign formUI><#if args.formUI??>${args.formUI}<#else>true</#if></#assign>
 
   <#if formUI == "true">
      <@formLib.renderFormsRuntime formId=formId />
   </#if>
    
   <div id="${formId}-container" class="form-container">
       
      <#if form.showCaption?exists && form.showCaption>
         <div id="${formId}-caption" class="caption"><span class="mandatory-indicator">*</span>${msg("form.required.fields")}</div>
      </#if>
          
      <#if form.mode != "view">
         <form id="${formId}" method="${form.method}" accept-charset="utf-8" enctype="${form.enctype}" action="${form.submissionUrl}">
      </#if>
       
      <div id="${formId}-fields" class="form-fields">  
        <div id="${formId}-tabview" class="yui-navset">  
            <ul class="yui-nav">
                <#list form.structure as item>
                    <#if item.kind == "set">
                        <li <#if item_index == 0>class="selected"</#if>><a href="#tab_${item_index}"><em>${item.label}</em></a></li>
                    </#if>
                </#list>
                <li><a href="#tab_others"><em>Others</em></a></li>
            </ul>                     
            <div class="yui-content">
                <#list form.structure as item>
                    <#if item.kind == "set">
                       <div id="tab_${item_index}">
                               <@renderSetWithoutColumns set=item />
                       </div>        
                    </#if>
                 </#list>
                 <div id="tab_others">
                    <#list form.structure as item>
                        <#if item.kind != "set">
                               <@formLib.renderField field=form.fields[item.id] />
                        </#if>
                     </#list>
                 </div>      
            </div>  
         </div>
      </div>
          
      <#if form.mode != "view">
         <@formLib.renderFormButtons formId=formId />
         </form>
      </#if>
 
   </div>
</#if>
 
<#macro renderSetWithColumns set>
   <#if set.appearance?exists>
      <#if set.appearance == "fieldset">
         <fieldset><legend>${set.label}</legend>
      <#elseif set.appearance == "panel">
         <div class="form-panel">             
            <div class="form-panel-body">
      </#if>
   </#if>
    
   <#list set.children as item>
      <#if item.kind == "set">
         <@renderSetWithColumns set=item />
      <#else>
         <#if (item_index % 2) == 0>
         <div class="yui-g"><div class="yui-u first">
         <#else>
         <div class="yui-u">
         </#if>
         <@formLib.renderField field=item />
         </div>
         <#if ((item_index % 2) != 0) || !item_has_next></div></#if>
      </#if>
   </#list>
    
   <#if set.appearance?exists>
      <#if set.appearance == "fieldset">
         </fieldset>
      <#elseif set.appearance == "panel">
            </div>
         </div>
      </#if>
   </#if>
</#macro>
 
<#macro renderSet set>
   <#if set.appearance?exists>
      <#if set.appearance == "fieldset">
         <fieldset><legend>${set.label}</legend>
      <#elseif set.appearance == "panel">
         <div class="form-panel">
            <div class="form-panel-heading">${set.label}</div>
            <div class="form-panel-body">
      <#elseif set.appearance == "accordion">
      <div class="yui-skin-sam">
          <div class="yui-cms-accordion multiple fade fixIE">       
              <div class="yui-cms-item yui-panel">
                  <div class="hd">${set.label}</div>
                  <div class="bd">
                    <div class="fixed">
      </#if>
   </#if>
    
   <#list set.children as item>
      <#if item.kind == "set">
         <@renderSet set=item />
      <#else>
         <@formLib.renderField field=item />
      </#if>
   </#list>
    
   <#if set.appearance?exists>
      <#if set.appearance == "fieldset">
         </fieldset>
      <#elseif set.appearance == "panel">
            </div>
         </div>
      <#elseif set.appearance == "accordion">
                    </div>
                </div>
            <div class="actions">
              <a href="#" class="accordionToggleItem"> </a>
            </div>
         </div>
       </div>
       </div>
      </#if>
   </#if>
</#macro>
 
<#macro renderSetWithoutColumns set>
   <#if set.appearance?exists>
      <#if set.appearance == "fieldset">
         <fieldset><legend>${set.label}</legend>
      <#elseif set.appearance == "panel">
         <div class="form-panel">
            <div class="form-panel-body">
      </#if>
   </#if>
    
   <#list set.children as item>
      <#if item.kind == "set">
         <@renderSet set=item />
      <#else>
         <@formLib.renderField field=item />
      </#if>
   </#list>
    
   <#if set.appearance?exists>
      <#if set.appearance == "fieldset">
         </fieldset>
      <#elseif set.appearance == "panel">
            </div>
         </div>
      </#if>
   </#if>
</#macro>
 
 
<script>
(function() {
    var tabView = new YAHOO.widget.TabView('${formId}-tabview');
})();
</script>