Magnolia 5.3 reached end of life on June 30, 2017. This branch is no longer supported, see End-of-life policy.

Page tree
Skip to end of metadata
Go to start of metadata

It is common to use a custom content app in a choose dialog. Here we create a dialog that allows editors to choose an image from Flickr. We use the Flickr browser app in a component template to browse the photos.

Required modules

Makes sure that your webapp contains the following modules from flickr-integration-parent:

  • flickr-templates
  • flickr-browser
  • flickr-accounts
  • flickr-integration

The flickr-templates module installs a component template with a choose dialog. The dialog launches the Flickr browser app to select a photo. The flickr-browser module contains a custom field and its definition and some custom classes. The flickr-accounts and flickr-integration modules are used by the flickr-browser module.

Creating a component template

Template definition

A template definition gives the component a name and makes it available to the system. The node name flickr-image-simple is used to the reference the component later.

 Click here to display the template definition

Node name



















Dialog definition

To select an item from a content app we usually use a Link field. However, the default link field is rather JCR centric and not suitable for choose dialogs that reach out to custom content apps. We have to create a custom field. See flickrPictureId in the dialog definition:

Node name
































Field properties:

  • appName: The name of the app we want to launch in the dialog.
  • class: The definition of the field to be used. Note that we don't use the default LinkFieldDefinition but a custom FlickrItemFieldDefinition. See field definition below.
  • contentPreviewDefinition: Renders a preview of the selected content.
    • class: FlickrItemPreviewComponent is a custom implementation of ContentPreviewComponent , see below.

The dialog will store the Flickr photo_id, for instance "14786302241", in a flickrPictureId property in the JCR.

Creating and registering a custom Link field

Since the default  LinkField  is not suitable we need a custom definition class and a custom factory class. Read Custom fields to understand what classes a custom field requires.

Field definition class

In the definition class all we have to do is to extend LinkFieldDefinition.
public class FlickrItemFieldDefinition extends LinkFieldDefinition {

Field factory class

In the factory class we override createChooseDialogCallback(). This method makes sure that the value which we store in the flickrPictureId property in the JCR is set to the field. We have the FlickrItemId of the selected item, from the ItemId we can access the photoId and set it to the same value.
public class FlickrItemFieldFactory extends LinkFieldFactory {
    private Field<String> field;
    public FlickrItemFieldFactory(LinkFieldDefinition definition, Item relatedFieldItem, AppController appController, UiContext uiContext, ComponentProvider componentProvider) {
        super(definition, relatedFieldItem, appController, uiContext, componentProvider);

    protected ChooseDialogCallback createChooseDialogCallback() {
        return new ChooseDialogCallback() {
            public void onItemChosen(String actionName, final Object chosenValue) {
                String newValue = null;
                if (chosenValue instanceof FlickrItemId) {
                    String photoId = ((FlickrItemId) chosenValue).getPhotoId();
                    if (StringUtils.isNotBlank(photoId)) {
                        newValue = photoId;
            public void onCancel() {
    protected Field<String> createFieldComponent() {
        field = super.createFieldComponent();
        return field;

Registering the custom field

Register the new field in the flickr-browser module since the field is specifically built to be used with the flickr-browser app.

Node nameValue











Now we can use the field like we already done in the Dialog.

Content preview component

A content preview component renders a preview of the selected photo in the choose dialog. The preview component typically displays an image thumbnail and some metadata. Here we create a FlickrItemPreviewComponent which displays a thumbnail and a photo title.

To build the custom preview component extend AbstractContentPreviewComponent :
public class FlickrItemPreviewComponent extends AbstractContentPreviewComponent<FlickrItem> {
    private FlickrBrowserPreviewImageProvider imageProvider;
    private FlickrService flickrService;
    public FlickrItemPreviewComponent(String workspace, FlickrService flickrService) {
        this.imageProvider = new FlickrBrowserPreviewImageProvider(flickrService);
        this.flickrService = flickrService;
        VerticalLayout verticalLayout = new VerticalLayout();
        verticalLayout.addComponent(new Label(""));
        rootLayout = verticalLayout;
    protected Component refreshContentDetail(FlickrItem item) {
        CssLayout layout = new CssLayout();
        displayProperty(item, FlickrItem.PROPERTY_TITLE, layout);
        displayProperty(item, FlickrItem.PROPERTY_DESCRIPTION, layout);
        return layout;
    protected Component refreshContentPreview(FlickrItem item) {
        String photoId = (String) item.getItemProperty(FlickrItem.PROPERTY_PHOTOID).getValue();
        Resource resource = imageProvider.getSmallThumbnailResource(photoId);
        Image image = new Image();
        return image;
    protected FlickrItem refreshItem(String itemPath) {
        if (StringUtils.isNotBlank(itemPath)) {
            Photo photo = flickrService.getPhoto(itemPath);
            if (photo != null) {
                FlickrItem flickrItem = FlickrItemUtil.createItemByPhoto(photo);
                if (flickrItem != null) {
                    return flickrItem;
        return null;
    private void displayProperty(FlickrItem item, String itemPropertyId, CssLayout layout) {
        String valueTxt = (String) item.getItemProperty(itemPropertyId).getValue();
        if (StringUtils.isNotBlank(valueTxt)) {
            layout.addComponent(new Label(valueTxt));