Create a Multifield in Multifield without any custom code

By | 08:52 Leave a Comment
This is a follow up to my post : http://cq5tutorials.blogspot.in/2014/04/cq5-multifield-in-multifield.html .  Here's a plug and play solution built by chaining adobe's multifield xtype with a couple of open source widgets.

Problem : Adobe's multifiled solution doesn't work with composite values. It stores value as a String if only one value is configured and as a String[] if multiple values are configured. A common work around to overcome this is create a custom composite field that concatenates the individual fields of a composite field into a Single string with a delimiter ( http://cq.shishank.info/2011/12/19/multifield-with-custom-xtype/ and http://stackoverflow.com/questions/26290908/multifield-component-issue/26294172 ) . This workaround fails when you want to have varying number of composite fields with multifield inside the composite field. A common requirement while creating listing components such as mega menus and accordions. A lot of guys end up dynamically including parsys for every menu coulmn or accordion block. The ideal solution would be to have a multifield in multifield (can be a little confusing for the author , but can be dealt with  authoring guide and pointers in the dialog )

Solution :  Use three widgets to create the multifield in multifield effect.
1) Multicomposite -  xtype that stores  each multifield entry as a child node with the fields as properties. [Developed by Citytech inc]

2) Multifieldpanel - xtype that stores a multifield as an array of json objects where each field is a property of the json object. [Developed by ACS]

3) Multifield - the out of box multifield xtype.

The fix  :  multicomposite  ( outer multifield )
                 |-fieldConfigs
                         |- field A (lets say a textfield , for the menu's coulmn name)
                         |- field B (a pathfield to configure the link for the column name )
                         |- field C (multifield , the inner multifield to hold sub menu entries )
                                  |-fieldConfig - xtype : multifieldpanel
                                        |- field Ca (textfield to hold title)
                                        |- field Cb (pathfield for the link)

Dialog  JSON -

{
  • matchBaseNamefalse,
  • xtype"multicompositefield",
  • name"./menu",
  • hideLabeltrue,
  • jcr:primaryType"cq:Widget",
  • fieldDescription" click + to add menu column",
  • fieldConfigs:
    {
    • jcr:primaryType"cq:WidgetCollection",
    • name:
      {
      • width"500",
      • fieldLabel"Name",
      • xtype"textfield",
      • allowBalnktrue,
      • name"title",
      • fieldLabel"Link Title",
      • jcr:primaryType"cq:Widget",
      },
    • link:
      {
      • xtype"pathfield",
      • fieldLabel"Link",
      • name"link",
      • jcr:primaryType"cq:Widget"
      },
    • submenu:
      {
      • xtype"multifield",
      • title"submenu",
      • fieldLabel"Submenu",
      • name"submenu",
      • collapsibletrue,
      • jcr:primaryType"cq:Widget",
      • fieldDescription"Click + to add sub menu entry",
      • fieldConfig:
        {
        • xtype"multifieldpanel",
        • hideLabelfalse,
        • jcr:primaryType"cq:Widget",
        • items:
          {
          • jcr:primaryType"cq:WidgetCollection",
          • title:
            {
            • key"title",
            • xtype"textfield",
            • fieldLabel"Link Title",
            • jcr:primaryType"cq:Widget"
            },
          • link:
            {
            • key"link",
            • fieldLabel"Link",
            • xtype"pathfield",
            • jcr:primaryType"cq:Widget"
            }
          }
        }
      }
    }
}       

The data is stored in the following format :

{
  • jcr:primaryType"nt:unstructured",
  • menu:
    {
    • jcr:primaryType"nt:unstructured",
    • item_1:
      {
      • submenu:
        [
        • "{"title":"Link 1","link":"http://cq5tutorials.blogspot.in"}",
        • "{"title":"Link 2","link":"http://cq5tutorials.blogspot.in"}"
        ],
      • title"Main Menu Item 1",
      • jcr:primaryType"nt:unstructured",
      },
    • item_2:
      {
      • submenu:
        [
        • "{"title":"Sub menu 1","link":"http://cq5tutorials.blogspot.in"}",
        • "{"title":"Sub menu 2","link":"http://cq5tutorials.blogspot.in"}"
        ],
      • title"Main Menu item 2",
      • jcr:primaryType"nt:unstructured",
      }
    }
}

Notice that the inner multifield (submenu) is stored as an array of json strings. There is a utility in ACS code to read entries from this :  http://adobe-consulting-services.github.io/acs-aem-commons/features/widgets.html


Few Drawbacks :

1) This xtype works only when it's on the first tab (or the tab that's active on dialog load ) of the dialog . Multifield dooesn't handle all the extjs events like the rest of the widgets as a result the inner panels don't get rendered if the widget is not visible on load. Should not cause an issue as long as its on the first tab of the dialog

2) The xtypes involved do not fire all events like the basic widgets , ex : beforeloadcontent . This can be a problem when you want to write few custom listeners .  If you know your way around extjs , this can still be accomplished by leveraging other events like the beforeadd.







0 comments:

Post a Comment