cancel
Showing results for 
Search instead for 
Did you mean: 

Cascading Dropdown in alfresco share

joshijimit
Champ on-the-rise
Champ on-the-rise
Hi All,

I have a requirement in my project to implement cascading dropdown in alfresco share.
I have followed the below link of jean barmash's blog and implemented cascading dropdown in alfresco explorer.

http://blogs.alfresco.com/wp/jbarmash/2008/08/18/implementing-cascading-dropdowns-for-editing-proper...

I have also got success to show the dropdown fields in alfresco share by wrapping it up in custom aspect.
but the problem now is custom component generator(TextFieldGenerator) is not being utilize in alfresco share as alfresco uses "Forms" to edit metadata.

I am finding the workaround to make it possible.
Any help from anyone would be of great help.

Regards,
Jimit
1 ACCEPTED ANSWER

scouil
Star Contributor
Star Contributor
As expected, defining the onchange event in javascript fixes it.
I ended up refactoring a bit my code and spliting it into 2 files:

/org/alfresco/components/form/controls/cascading-dropdowns.ftl :

<#include "/org/alfresco/components/form/controls/common/utils.inc.ftl" />
<#include "/org/alfresco/components/form/controls/common/cascadingDropdownUtils.inc.ftl" />

<!– current value –>
<#assign fieldValue=field.value>

<!– handle default value for empty current value –>
<#if fieldValue?string == "" && field.control.params.defaultValueContextProperty??>
   <#if context.properties[field.control.params.defaultValueContextProperty]??>
      <#assign fieldValue = context.properties[field.control.params.defaultValueContextProperty]>
   <#elseif args[field.control.params.defaultValueContextProperty]??>
      <#assign fieldValue = args[field.control.params.defaultValueContextProperty]>
   </#if>
</#if>

<div class="form-field">
   <!– readonly mode. No action required, display the composed value as is –>
   <#if form.mode == "view">
      <div class="viewmode-field">
         <#if field.mandatory && !(fieldValue?is_number) && fieldValue?string == "">
            <span class="incomplete-warning"><img src="${url.context}/res/components/form/images/warning-16.png" title="${msg("form.field.incomplete" )}" /><span>
         </#if>
         <span class="viewmode-label">${field.label?html}:</span>
         <#if fieldValue?string == "">
            <#assign valueToShow=msg("form.control.novalue" )>
         <#else>
            <#assign valueToShow=fieldValue>
            <#if field.control.params.options?? && field.control.params.options != "">
               <#list field.control.params.options?split(optionSeparator) as nameValue>
                  <#if nameValue?index_of(labelSeparator) == -1>
                     <#if nameValue == fieldValue?string || (fieldValue?is_number && fieldValue?c == nameValue)>
                        <#assign valueToShow=nameValue>
                        <#break>
                     </#if>
                  <#else>
                     <#assign choice=nameValue?split(labelSeparator)>
                     <#if choice[0] == fieldValue?string || (fieldValue?is_number && fieldValue?c == choice[0])>
                        <#assign valueToShow=msgValue(choice[1])>
                        <#break>
                     </#if>
                  </#if>
               </#list>
            </#if>
         </#if>
         <span class="viewmode-value">${valueToShow?html}</span>
      </div>
   <#else>
     <!– Editable mode. –>
     <!– let's keep a single label for both fields –>
      <label for="${fieldHtmlId}">${field.label?html}:<#if field.mandatory><span class="mandatory-indicator">${msg("form.required.fields.marker" )}</span></#if></label>
      <#if field.control.params.options?? && field.control.params.options != "">
       <!– first select for the parent value –>
         <select id="parent-${fieldHtmlId}" tabindex="0"
               <#if field.description??>title="${field.description}"</#if>
               <#if field.control.params.size??>size="${field.control.params.size}"</#if>
               <#if field.control.params.styleClass??>class="${field.control.params.styleClass}"</#if>
               <#if field.control.params.style??>style="${field.control.params.style}"</#if>
               <#if field.disabled  && !(field.control.params.forceEditable?? && field.control.params.forceEditable == "true" )>disabled="true"</#if>>
         </select>
      
       <!– second select for the child value –>
         <select id="child-${fieldHtmlId}" name="${field.name}" tabindex="0"
               <#if field.description??>title="${field.description}"</#if>
               <#if field.control.params.size??>size="${field.control.params.size}"</#if>
               <#if field.control.params.styleClass??>class="${field.control.params.styleClass}"</#if>
               <#if field.control.params.style??>style="${field.control.params.style}"</#if>
               <#if field.disabled  && !(field.control.params.forceEditable?? && field.control.params.forceEditable == "true" )>disabled="true"</#if>>
         </select>
      
       <!– hidden field containing the final value (e.g. the one sent to the server and stored in database) –>
       <input type="hidden" id="${fieldHtmlId}" name="${field.name}" />
      
         <@formLib.renderFieldHelp field=field />
      <#else>
         <div id="${fieldHtmlId}" class="missing-options">${msg("form.control.selectone.missing-options" )}</div>
      </#if>
   </#if>
</div>

<!– IMPORTANT: this script must execute after the fields are created –>
<script type="text/javascript">//<![CDATA[
   setTimeout(function(){populateSelects("${field.control.params.options}", "${fieldValue}", "parent-${fieldHtmlId}", "child-${fieldHtmlId}", "${fieldHtmlId}");}, 1000);
//]]></script>


and /org/alfresco/components/form/controls/common/cascadingDropdownUtils.inc.ftl :

<!– defines how the option list elements are separated when passed to the client –>
<#if field.control.params.optionSeparator??>
   <#assign optionSeparator=field.control.params.optionSeparator>
<#else>
   <#assign optionSeparator=",">
</#if>

<!– defines how the label list elements are separated when passed to the client –>
<#if field.control.params.labelSeparator??>
   <#assign labelSeparator=field.control.params.labelSeparator>
<#else>
   <#assign labelSeparator="|">
</#if>

<script type="text/javascript">//<![CDATA[
<!– defines how the option list elements are separated when passed to the client –>
<#if field.control.params.optionSeparator??>
   <#assign optionSeparator=field.control.params.optionSeparator>
<#else>
   <#assign optionSeparator=",">
</#if>

<!– defines how the label list elements are separated when passed to the client –>
<#if field.control.params.labelSeparator??>
   <#assign labelSeparator=field.control.params.labelSeparator>
<#else>
   <#assign labelSeparator="|">
</#if>

<script type="text/javascript">//<![CDATA[
   /* string used to separate the parent from the child */
   var OPTION_SEPARATOR = "/";

   /**
   * Functions used to split and synchronize the data between the 2 lists.
   **/
   
   /**
   *   @param stringValues: string containing the available values for the given field
   *   @returns a javascript object containing those values
   **/
   function getValsArrayFromString(stringValues) {
      //array with the options
      var valsArray = stringValues.split("${optionSeparator}");
      //remove the labels
      for (var i = 0; i < valsArray.length; i++) {
         if(valsArray.indexOf("${labelSeparator}") != -1) {
            valsArray = valsArray.substr(0,valsArray.indexOf("${labelSeparator}"));
         }
      }
      return valsArray;
   }

   /**
   * Extracts the parent value from the full value of the option
   **/
   function getParentValue(fullValue) {
      return fullValue.substr(0,fullValue.indexOf(OPTION_SEPARATOR));
   }

   /**
   * Extracts the child value from the full value of the option
   **/
   function getChildValue(fullValue) {
      return fullValue.substr(fullValue.indexOf(OPTION_SEPARATOR) + 1);
   }

   /**
   * Parent value have been changed.
   * Reset the current total value, child value and updates the available child values
   **/
   function onChangeParentValue(valsArray, parentId, childId, totalId) {
      var parentValue = document.getElementById(parentId).value;
      var childSelect = document.getElementById(childId);
      
      /* empty the child select */
      while(childSelect.firstChild) {
         childSelect.removeChild(childSelect.firstChild);
      }
      
      /* fill the child select with the new values */
      for (var i = 0; i < valsArray.length; i++) {
         if ( getParentValue(valsArray) == parentValue) {
            var childValue = getChildValue(valsArray);
            var childOption = document.createElement("option");
            childOption.value = childValue;
            childOption.innerHTML = childValue;
            childSelect.appendChild(childOption);
         }
      }
   }

   /**
   * Child value have been changed.
   * Update the total value
   **/
   function onChangeChildValue(parentId, childId, totalId) {
      var parentValue = document.getElementById(parentId).value;
      var childValue = document.getElementById(childId).value;
      document.getElementById(totalId).value = parentValue + OPTION_SEPARATOR + childValue;
   }

   /**
   * Initial filling of the parent values available
   * TODO: handle default value
   **/
   function populateSelects(stringValues, initialValue, parentId, childId, totalId) {
      /* get an array from the string values */
      var valsArray = getValsArrayFromString(stringValues);
      var parentSelect = document.getElementById(parentId);
      /* we only want to display each parent value once. This object keeps track of the already added ones */
      var uniqueParentValues = {};
      
      /* populate parent select */
      for (var i = 0; i < valsArray.length; i++) {
         var realV = getParentValue(valsArray);
         if(!uniqueParentValues.hasOwnProperty(realV)) {
            uniqueParentValues[realV] = true;
            
            /* create new option for the parent select */
            var parOption = document.createElement("option");
            parOption.value = realV;
            parOption.innerHTML = realV;
            if(realV == getParentValue(initialValue)) {
               parOption.selected = "selected";
            }
            parentSelect.appendChild(parOption);
         }
      }
      parentSelect.onchange = function(){onChangeParentValue(valsArray, parentId, childId, totalId);};
      
      /* populate child select */
      onChangeParentValue(valsArray, parentId, childId, totalId);
      
      /* sets the correct child value */
      var childSelect = document.getElementById(childId);
      childSelect.value = getChildValue(initialValue);
      childSelect.onchange = function(){onChangeChildValue(parentId, childId, totalId);};
      onChangeChildValue(parentId, childId, totalId);
   }
//]]></script>


IE advanced search now works as expected.

View answer in original post

28 REPLIES 28

joshijimit
Champ on-the-rise
Champ on-the-rise
Hi All,

I am ready with the initial draft of the implementation. Here we go.
Step by step approach
1) Create content Model with dynamic constraint. (cascadingModel.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!– Definition of new Model –>
<model name="ccd:cascadingmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">

   <!– Optional meta-data about the model –>
   <description>Cascading Model</description>
   <author>Cybage</author>
   <version>1.0</version>

   <!– Imports are required to allow references to definitions in other models –>
   <imports>
      <!– Import Alfresco Dictionary Definitions –>
      <import uri="http://www.alfresco.org/model/dictionary/1.0"
         prefix="d" />
      <!– Import Alfresco Content Domain Model Definitions –>
      <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" />
      <import uri="http://www.alfresco.org/model/system/1.0" prefix="sys" />
   </imports>

   <!– Introduction of new namespaces defined by this model –>
   <namespaces>
      <namespace uri="http://www.cascading.com/model/content/1.0"
         prefix="ccd" />
   </namespaces>

   <constraints>
      
      <constraint name="ccd:productList"
         type="com.mycomp.cascading.demo.ListOfValuesProductConstraint">
         <parameter name="allowedValues">
            <list>
            </list>
         </parameter>
      </constraint>
      <constraint name="ccd:trimList"
         type="com.mycomp.cascading.demo.ListOfValuesTrimConstraint">
         <parameter name="allowedValues">
            <list>
            </list>
         </parameter>
      </constraint>
      <constraint name="ccd:vehicleColorList"
         type="com.mycomp.cascading.demo.ListOfValuesVehicleColorConstraint">
         <parameter name="allowedValues">
            <list>
            </list>
         </parameter>
      </constraint>   
      
   </constraints>

   <types>
      <!– Enterprise-wide generic document type –>
      <type name="ccd:doc">
         <title>Cascading Document</title>
         <parent>cm:content</parent>
      </type>
   </types>
   <aspects>
      <aspect name="ccd:imageAsset">
         <title>Cascading Aspect</title>
         <properties>
            <property name="ccd:producta">
               <title>Product Name</title>
               <type>d:text</type>
               <constraints>
                  <constraint ref="ccd:productList" />
               </constraints>               
            </property>
            <property name="ccd:trima">
               <title>Trim</title>
               <type>d:text</type>   
               <constraints>
                  <constraint ref="ccd:trimList" />
               </constraints>            
            </property>
            <property name="ccd:vehicleColora">
               <title>Vehicle Color</title>
               <type>d:text</type>
               <constraints>
                  <constraint ref="ccd:vehicleColorList" />
               </constraints>               
            </property>
         </properties>
      </aspect>
   </aspects>
</model>

2) Create constraint that loads values from database. (ListOfValuesProductConstraint)


package com.mycomp.cascading.demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.faces.model.SelectItem;

import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.generator.BaseComponentGenerator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ListOfValuesProductConstraint extends SearchBasedListConstraint {

   private static Log logger = LogFactory.getLog(BaseComponentGenerator.class);

   private static final long serialVersionUID = 1;
   private Node node = null;

   public Node getNode() {
      return node;
   }

   public void setNode(Node node) {
      this.node = node;
   }

   private List<String> allowedLabels;

   public void setAllowedValues(List allowedValues) {
   }

   public void setCaseSensitive(boolean caseSensitive) {
   }

   public void initialize() {
      super.setCaseSensitive(false);
      this.loadDB();
   }

   public List<String> getAllowedLabels() {
      return this.allowedLabels;
   }

   public void setAllowedLabels(List<String> allowedLabels) {
      this.allowedLabels = allowedLabels;
   }

   public List<SelectItem> getSelectItemList() {
      List<SelectItem> result = new ArrayList<SelectItem>(this
            .getAllowedValues().size());
      for (int i = 0; i < this.getAllowedValues().size(); i++) {
         result.add(new SelectItem((Object) this.getAllowedValues().get(i),
               this.allowedLabels.get(i)));
      }
      return result;
   }

   protected void loadDB() {

      String driverName = "org.gjt.mm.mysql.Driver";
      String serverName = "localhost";
      String mydatabase = "cascading";
      String username = "root";
      String password = "root";

      List<String> av = new ArrayList<String>();
      List<String> al = new ArrayList<String>();
      Connection connection = null;
      Statement stmt = null;
      ResultSet rs = null;
      

         try {

            Class.forName(driverName);
            String url = "jdbc:mysql://" + serverName + "/" + mydatabase;
            connection = DriverManager.getConnection(url, username,
                  password);
            stmt = connection.createStatement();
            rs = stmt.executeQuery("select distinct product from imageasset");
            av.add("–Select–");
            while (rs.next()) {
               av.add(rs.getString("product"));
               //al.add(rs.getString("label"));
            }
         } catch (Exception e) {
         } finally {
            try {
               if (rs != null)
                  rs.close();
               if (stmt != null)
                  stmt.close();
               if (connection != null && !connection.isClosed())
                  connection.close();
            } catch (SQLException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
            }
         }

         super.setAllowedValues(av);
         //this.setAllowedLabels(al);
      }
   
}

3) Create custom template of Alfresco Share to register onChange event call java backed web script on change of values in dropdown. (selectoneCustom.ftl)
Note: Needs to create separate template for each parent dropdown as we are passing child reference in script and make an Ajax call to fill dependent dropdown.


<#include "/org/alfresco/components/form/controls/common/utils.inc.ftl" />
<script language="JavaScript" type="text/javascript">

function getProduct(frm,selectedValue) {

   var xmlhttp;
   
   if (window.XMLHttpRequest) {
         xmlhttp = new XMLHttpRequest();
   } else {
         xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
   }
   
   xmlhttp.onreadystatechange = function() {
      var ticket;
      
      if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
         
            
            //var jsonString = xmlhttp.responseText;                        
            //var myFirstJSON = eval('(' + jsonString + ')');
            
            var theSel = frm.prop_ccd_trima;                     
            theSel.disabled = false;            
            
            removeAllOptions(theSel);      
            //alert(selectedValue +" "+ myFirstJSON[0][0]);            
            //insertOldSchool(theSel,myFirstJSON[0][0],myFirstJSON[0][0]);
            
            var resp = xmlhttp.responseText;
            var respArr = resp.split(',');
            for(var i=0;i<respArr.length;i++){
               insertOldSchool(theSel,respArr[i],respArr[i]);
            }
            
            
      }      
   };
   xmlhttp.open("GET","http://jimitj/alfresco/service/demo/cascading?field=trim&key=product&value='+selectedValue ,true);

   xmlhttp.send();

}

</script>

<#if field.control.params.optionSeparator??>
   <#assign optionSeparator=field.control.params.optionSeparator>
<#else>
   <#assign optionSeparator=",">
</#if>
<#if field.control.params.labelSeparator??>
   <#assign labelSeparator=field.control.params.labelSeparator>
<#else>
   <#assign labelSeparator="|">
</#if>

<div class="form-field">
   <#if form.mode == "view">
      <div class="viewmode-field">
         <#if field.mandatory && !(field.value?is_number) && field.value?string == "">
            <span class="incomplete-warning"><img src="${url.context}/res/components/form/images/warning-16.png" title="${msg("form.field.incomplete")}" /><span>
         </#if>
         <#if field.control.params.options?? && field.control.params.options != "">
         <span class="viewmode-label">${field.label?html}:</span>        
         <#if field.value?string == "">
            <#assign valueToShow=msg("form.control.novalue")>           
         <#else>
            <#assign valueToShow=field.value>
            <#list field.control.params.options?split(optionSeparator) as nameValue>
               <#if nameValue?index_of(labelSeparator) == -1>
                  <#if nameValue == field.value?string || (field.value?is_number && field.value?c == nameValue)>
                     <#assign valueToShow=nameValue>
                     <#break>
                  </#if>
               <#else>
                  <#assign choice=nameValue?split(labelSeparator)>
                  <#if choice[0] == field.value?string || (field.value?is_number && field.value?c == choice[0])>
                     <#assign valueToShow=msgValue(choice[1])>
                     <#break>
                  </#if>
               </#if>
            </#list>
         </#if>        
         <span class="viewmode-value">${valueToShow?html}</span>
         </#if>
      </div>
   <#else>
     
      <#if field.control.params.options?? && field.control.params.options != "">
         <label for="${fieldHtmlId}">${field.label?html}:<#if field.mandatory><span class="mandatory-indicator">${msg("form.required.fields.marker")}</span></#if></label>   
         <select id="${fieldHtmlId}" name="${field.name}" tabindex="0" ONCHANGE="getProduct(this.form,this.options[this.selectedIndex].value);"
               <#if field.description??>title="${field.description}"</#if>
               <#if field.control.params.size??>size="${field.control.params.size}"</#if>
               <#if field.control.params.styleClass??>class="${field.control.params.styleClass}"</#if>
               <#if field.control.params.style??>style="${field.control.params.style}"</#if>
               <#if field.disabled  && !(field.control.params.forceEditable?? && field.control.params.forceEditable == "true")>disabled="true"</#if>>
               <#list field.control.params.options?split(optionSeparator) as nameValue>
                  <#if nameValue?index_of(labelSeparator) == -1>
                     <option value="${nameValue?html}"<#if nameValue == field.value?string || (field.value?is_number && field.value?c == nameValue)> selected="selected"</#if>>${nameValue?html}</option>
                  <#else>
                     <#assign choice=nameValue?split(labelSeparator)>
                     <option value="${choice[0]?html}"<#if choice[0] == field.value?string || (field.value?is_number && field.value?c == choice[0])> selected="selected"</#if>>${msgValue(choice[1])?html}</option>
                  </#if>
               </#list>
         </select>
         <@formLib.renderFieldHelp field=field />
      <#else>             
       
      </#if>
   </#if>
</div>

4) Share-config-custom.xml to show properties in alfresco share.


config  evaluator="node-type" condition="cm:content">
      <forms>
         <!– Default form configuration used on the document details and edit metadata pages –>
         <form>
            <field-visibility>         
             
              
               <show id="ccd:producta"/>
               <show id="ccd:trima"/>
               <show id="ccd:vehicleColora"/>
              
             
            </field-visibility>
             <appearance>           
             <field id="ccd:producta" label="Product">
                <control template="controls/selectoneCustom.ftl">                  
                </control>               

             </field>
             <field id="ccd:trima" label="Trim">
                <control template="controls/selectoneDepenedentDisable.ftl">                  
                </control>
             </field>
             <field id="ccd:vehicleColora" label="Vehicle Color">
                <control template="controls/selectoneDisable.ftl">                  
                </control>
             </field>
           
          </appearance>

         </form>

         <!– Document Library pop-up Edit Metadata form –>
         <form id="doclib-simple-metadata">
            <field-visibility>
           
               <show id="ccd:producta"/>
               <show id="ccd:trima"/>
               <show id="ccd:vehicleColora"/>
             
            </field-visibility>
            <edit-form template="../documentlibrary/forms/doclib-simple-metadata.ftl" />
             <appearance>           
             <field id="ccd:producta" label="Product">
                <control template="controls/selectoneCustom.ftl">                  
                </control>               

             </field>
             <field id="ccd:trima" label="Trim">
                <control template="controls/selectoneDepenedentDisable.ftl">                  
                </control>
             </field>
             <field id="ccd:vehicleColora" label="Vehicle Color">
                <control template="controls/selectoneDisable.ftl">                  
                </control>
             </field>
           
          </appearance>
           
         </form>

         <!– Document Library Inline Edit form –>
         <form id="doclib-inline-edit">
            <field-visibility>
              
            
               <show id="ccd:producta"/>
               <show id="ccd:trima"/>
               <show id="ccd:vehicleColora"/>
           
            </field-visibility>
           
         </form>
      </forms>
    

   </config>

5) Java backed Web script: Fetch values from database according to the value passed to it from web script call. (CascadingWebScript.java)


package com.mycomp.cascading.demo;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.servlet.http.HttpServletRequest;

import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest;

public class CascadingWebScript extends AbstractWebScript {

   public void execute(WebScriptRequest req, WebScriptResponse res)
         throws IOException {

      String driverName = "org.gjt.mm.mysql.Driver";
      String serverName = "localhost";
      String mydatabase = "cascading";
      String username = "root";
      String password = "root";

      Connection connection = null;
      Statement stmt = null;
      ResultSet rs = null;

      try {

         HttpServletRequest httpReq = ((WebScriptServletRequest) req)
               .getHttpServletRequest();

         String field = httpReq.getParameter("field");
         String key = httpReq.getParameter("key");
         String value = httpReq.getParameter("value");

         System.out.println("Debugg : " + field + ":" + key + ":" + value);
         Class.forName(driverName);
         String url = "jdbc:mysql://" + serverName + "/" + mydatabase;
         connection = DriverManager.getConnection(url, username, password);
         stmt = connection.createStatement();

         rs = stmt.executeQuery("select distinct " + field
               + " from imageasset where " + key + "= '" + value + "'");

         String response = "–Select–,";
         while (rs.next()) {
            if (rs.isLast())
               response += rs.getString(field);
            else
               response += rs.getString(field) + ",";
         }

         System.out.println("Debugg : " + response);

         res.getWriter().write(response);

      } catch (Exception e) {
         e.printStackTrace();
         res.getWriter().write("Error");
      } finally {
         try {
            if (rs != null)
               rs.close();
            if (stmt != null)
               stmt.close();
            if (connection != null && !connection.isClosed())
               connection.close();
         } catch (SQLException e) {
            e.printStackTrace();
            res.getWriter().write("Error");
         }
      }
   }
}

6) Config file for Java backed web script. (cascading.get.desc.xml)
Needs to put it under: Alfresco_Home\ tomcat\webapps\alfresco\WEB-INF\classes\alfresco\templates\webscripts\org\alfresco\demo


<webscript>
  <shortname>Cascading Web script </shortname>
  <description>Get values from database</description>
  <url>/demo/cascading?field={field}&amp;key={key}&amp;value={value}</url>
  <authentication>none</authentication>
  <format default="json">argument</format>
</webscript>

7)   Needs to put an entry to define a script as java backed webscript in web-scripts-application-context.xml under: Alfresco_Home\ tomcat\webapps\alfresco\WEB-INF\classes\alfresco
Note: Watch out Naming convension of bean id.


<bean id="webscript.org.alfresco.demo.cascading.get"
         class="com.mycomp.cascading.demo.CascadingWebScript"
         parent="webscript">
   </bean>

8. If you are calling alfresco web script from Liferay portlet on client side (ajax call), you need to implement Apache as a proxy server(add mod_proxy module in apache) to alfresco and Liferay to make cross browser scripting enable.

Let me know if you face any problem while implementation.

csabee
Champ in-the-making
Champ in-the-making
Hi there,

I've found lots of errors/problems in this implementation (I've been trying to implement this for 3 days based on your results).

Here are some problems:
1. function insertOldSchool is missing implementation
2. I don't know why, but the xmlhttp.onreadystatechange() call isn't being executed.
However, from firebug I can see the correct response
3. Lots of things are hardcoded. I don't know how to correctly implement for the webscript to get database connection settings from a file, or a model.
4. The ftl won't render the fields if their choicelist is empty. But if they aren't rendered, they won't be updated by their parents (no element found…)

Thanks,

csabee
Champ in-the-making
Champ in-the-making
OK, for problem 2. here is the solution:
- Be sure, that all the .ftl -s will call function differenting in names for the field's onchange event

Here is an other problem:
removeAllOptions() isn't defined

johanpi
Champ in-the-making
Champ in-the-making
I got everything working…

Implemented one class with parameters to use on multiple dropdown boxes.

Problem is the constraint on the sub-dropdown. It must have all the values of the constraints and initially is disabled but filled with all the values.

After selecting the fist dropdown it filters the second and works.
Problem every time it is edited the second dropdown have all the values…

Just some feedback.
Regards

joshijimit
Champ on-the-rise
Champ on-the-rise
Hi All,

I have implemented it successfully and its running on production server without any problem.
Send me PM if you want to get help to implement this functionality in your project.

-Jimit

kevinchen
Champ in-the-making
Champ in-the-making

i want the source code ,could you send it to my email (chenzixia@fiberhome.com)  ,thanks

Hi Kevin,

I have used https://github.com/douglascrp/alfresco-value-assistance this

project for cascading dropdown. Please try this.

Thanks

Hiten Rastogi

Sr. Software Engineer

Mobile: +91 9899586608

Email: hiten.rastogi@eisenvault.com <vipul.swarup@eisenvault.com>

thank you very much, it's worked

Hello Friend,

I'm new in Alfresco. How Can I do to implement this github solution working on my Alfresco Communit.

What I have to do? What steps I have to fallow in order to get it working? Where I have to put this folders ( alfresco-value-assistance-repo and alfresco-value-assistance-share)  into Alfresco ?

Thanks in advance for your help.

Regards,

Geovanny C.

you should learn alfresco SDK  and install AMP files into  your Alfresco Community, you can find video course in youtube  

Alfresco SDK 2.2.0 | Alfresco Documentation