cancel
Showing results for 
Search instead for 
Did you mean: 

Freemarker Custom View

dinger
Champ in-the-making
Champ in-the-making
I'm trying to write a custom view that displays files that have a custom aspect added (and hence custom metadata). I want to be able to sort on the the custom metadata field.

To achieve this I'm using a list?sort_by(["properties","custom:metadata"]) type sort and then displaying the results. However, if the current node doesn't have the specified property then it doesn't work. Not all nodes are guaranteed to have the custom field so I need to do a pre-filter first.

How do I achieve this in Freemarker? I've tried creating a list within a list but it doesn't work.

Cheers

Rob
6 REPLIES 6

mikeh
Star Contributor
Star Contributor
Hi

Unfortunately you've hit a limitation of Freemarker-only custom views. As you've discovered, Freemarker is very sensitive to missing or null values in lists, so you need to prefilter using JavaScript, which means converting your customer view code into a webscript and applying this to the space. The second "gotcha" is that there's currently no UI for this last step.

Fortunately there is a solution! There's a programmatic way of making a webscript into a custom view. I'm not 100% sure which version this was added in (and the developer is on paternity leave right now) but I'd expect it to at least be in 2.1.1E.

You need to add the cm:webscriptable aspect to a space with the cm:webscript property containing a relative* URL to the webscript rendering the view (*relative to the /alfresco/ web app).

Here's a webscript which will enable you to do this, so first create and register this script:

webscriptable.get.desc.xml
<webscript>
  <shortname>WebScript Custom View</shortname>
  <description>Add webscript aspect to space node</description>
  <url>/webscriptable?n={nodeRef}&amp;w={webscriptUrl}</url>
  <format default="html"/>
  <authentication>admin</authentication>
  <transaction>required</transaction>
</webscript>
(Change the URL and authentication details to suit your deployment)

webscriptable.get.js
if (args["n"] != null)
{
   var dest = search.findNode(args["n"]);
   if (dest != null)
   {
      if (args["add"] != null)
      {
         dest.addAspect("cm:webscriptable");
         dest.properties["cm:webscript"] = args["w"];
      }
      else
      {
         dest.removeAspect("cm:webscriptable");
      }
      dest.save();
   }
}

webscriptable.get.html.ftl
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
   <title>WebScript Custom View</title>
   <style>
   body {
      font-family: Verdana, Helvetica, sans-serif;
      font-size: 10pt;
   }
   .label {
      float: left;
      width: 10em;
   }
   .data {
      float: left;
   }
   .field {
      clear: left;
      float: left;
      padding: 8px;
   }
   </style>
</head>
<body>
<h3>WebScript Custom View</h3>
   <form action="${url.serviceContext}${url.match}" method="get">
      <div class="field">
         <span class="label">Space nodeRef:</span>
         <span class="data"><input type="text" name="n" size="64" /><br />e.g. &quot;workspace://SpacesStore/e3741425-35cf-11dc-9762-4b73d0280543&quot;</span>
      </div>
      <div class="field">
         <span class="label">Webscript URL:</span>
         <span class="data"><input type="text" name="w" size="128" value="/wcservice/PATH/TO/WEBSCRIPT?nodeRef={noderef}" /></span>
      </div>
      <div class="field">
         <span><input type="submit" value="Add" name="add" /></span>
         <span><input type="submit" value="Remove" name="remove" /></span>
      </div>
   </form>
</body>
</html>

When you run this webscript, you need the nodeRef of the space you want to customise and the URL of your custom view webscript - note the latter should start with /wcservice/ to use the right authenticator servlet (see the example within the html).

Your own custom view webscript will automatically get passed the nodeRef of the space, so you can use something like
var nodeRef = args["nodeRef"];
var space = search.findNode(nodeRef);
in your custom view's javascript.

Final note: the "webscriptable" webscript above also supplies a remove action, as there was a bug in the Web Client UI whereby this aspect didn't get removed using the normal trashcan icon.

Let me know how you get on….

Thanks,
Mike

dinger
Champ in-the-making
Champ in-the-making
Mike,

Finally managed to get it working: thanks!

When is the UI going to be added?

Cheers

Rob

dinger
Champ in-the-making
Champ in-the-making
Mike,

Had a quick question: is there any easy way to apply the webscriptable aspect to more than one node at a time? Say a hierarchy of nodes?

Cheers

Rob

mikeh
Star Contributor
Star Contributor
When is the UI going to be added?
Good question - I don't think it's being planned at the moment. If you'd like to raise an improvement request in JIRA this would help.

Had a quick question: is there any easy way to apply the webscriptable aspect to more than one node at a time? Say a hierarchy of nodes?
You should be able to take the example posted in this topic and apply it to the script above, looping through dest's children.

Thanks,
Mike

dinger
Champ in-the-making
Champ in-the-making
Thanks Mike.

For those that are interested, here is the JIRA http://issues.alfresco.com/browse/AWC-1878

Rob

stephane_botel1
Champ in-the-making
Champ in-the-making
Hello,
One year after but I am new to Alfresco.
I give a very simple solution I used, even if that filters the results perharps more than wanted.
It's up to you.
So I just filtered the search results by adding  "AND  (ISNOTNULL:custom\\:metadata)" to the query string.

If it can help.

See you

Stephane