Monday, May 27, 2013

[Alfresco/Share] Configure Inline Editable on your custom content

I did not find anything online that explained in one post how I could setup a custom content as Inline Editable. I gathered bits and pieces from several places, but...

First, you have to specify in your content model that the custom content type in question should be handled as inline editable. You do this by defining the aspect app:inlineeditable as a mandatory aspect of the content type. Don't forget to import the application content model so that you can use the app namespace. Here's a snippet for reference.

<?xml version="1.0" encoding="UTF-8"?>

<model name="losi:SampleModel"
       xmlns="http://www.alfresco.org/model/dictionary/1.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.alfresco.org/model/dictionary/1.0">

    <description>Sample Model</description>
    <author>Juan Jimenez</author>
    <version>1.0</version>

    <imports>
        <import uri="http://www.alfresco.org/model/application/1.0" prefix="app"/>
        <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
        <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
        ...snip...
    </imports>

    <namespaces>
        <namespace uri="http://losi.co/model/sample/1.0" prefix="losi"/>
    </namespaces>

    ...snip...
    <types>

        ...snip...
        <type name="losi:CustomContent">
            <title>CustomContent</title>
            <parent>cm:content</parent>
            ...snip...
            <mandatory-aspects>
                <aspect>app:inlineeditable</aspect>
            </mandatory-aspects>
        </type>
        ...snip...

    </types>
    ...snip...

</model>

What this configuration does, is tell Share (or Alfresco Explorer for that matter) that whenever an element of type losi:CustomContent is managed in the document library details page, it will enable the Inline Edit action button. But this alone will not do the complete job. You still need to specify Share that you want to display the control to edit the content of the target element, i.e. cm:content. There are to configurations for defining the element's metadata forms, one for creating it and another for editing it.

<!-- for creating -->
<config evaluator="model-type" condition="losi:CustomContent">
    <forms>
        <form>
           <field-visibility>
                <show id="cm:name"/>
                <show id="cm:title"/>
                <show id="cm:description"/>
            </field-visibility>
        </form>
    </forms>
</config>

<!-- for editing -->
<config evaluator="node-type" condition="losi:CustomContent">
    <forms>
        <form>
            <field-visibility>
                <show id="cm:name"/>
                <show id="cm:title"/>
                <show id="cm:description"/>
                <show id="cm:content"/>
            </field-visibility>
        </form>
    </forms>
</config>

I was having trouble with the create one; because I did not wanted to add content at create, but rather enable the user only to add content when editing. For some reason, the inline edit form and the edit properties where not displaying the control to edit the content. The reason is, that since in the create form the content was not being initialized, Share did not know how to render the control to edit content. For instance, if I created a behavior that added default content to any losi:CustomContent and bind it to node create policy for this type, the inline edit for the newly created custom content would behave as expected, i.e. the correct control is rendered.

I though that there should be a simpler way to fix that, so browse through Share config files, and noticed that the cm:content form is defined so that the mimetype is provided as a parameter (within the GET request) and sets it as a hidden field in the form. I figured that I could probably do the same for my CustomContent... and it worked. This is how it ended up:

<!-- for creating -->
<config evaluator="model-type" condition="losi:CustomContent">
    <forms>
        <form>
           <field-visibility>
                <show id="cm:name"/>
                <show id="cm:title"/>
                <show id="cm:description"/>
                <show id="mimetype"/>
                <show id="cm:content"/>
            </field-visibility>
            <appearance>
                <field id="mimetype">
                    <control template="/org/alfresco/components/form/controls/hidden.ftl">
                        <control-param name="contextProperty">mimeType</control-param>
                    </control>
                </field>
                <field id="cm:content">
                    <control template="/org/alfresco/components/form/controls/hidden.ftl"/>
                </field>
            </appearance>
        </form>
    </forms>
</config>

In addition, by default Share will use the form definition for editing, defined at node-type evaluator. But, if you want to define a separate form for inline edit, you can do so by adding another form to the list of forms under the node-type evaluator, with the id doclib-inline-edit.

<!-- for editing -->
<config evaluator="node-type" condition="losi:CustomContent">
    <forms>
        ...snip...

        <!-- Document Library Inline Edit form -->
        <form id="doclib-inline-edit">
            <field-visibility>
                <show id="cm:name" />
                <show id="cm:content" force="true" />
            </field-visibility>
        </form>
    </forms>
</config>

Once again, I hope this is helpful for others looking to implement similar scenarios.