This page explains how to get content from an app and display it on a page using templates.

Eric manages his cars in the Products app. The browser subapp (left) displays all the cars and the detail subapp (right) allows Eric to edit a single car.

  

Create a component that renders a list of cars on the website. The component should show each car's name, description and image.

Creating a content-items-list component

Component definition

Create a component definition:

/one-pager-module/templates/components/content-items-list.yaml
 templateScript: /one-pager-module/templates/components/content-items-list.ftl
dialog: one-pager-module:components/content-items-list
renderType: freemarker
title: Content app items list

Dialog definition

Create a dialog with the following fields:

  • title for the cars section on the page.
  • subText to enter some introduction text about this particular selection of cars.
  • productFolderRef link field that allows the user to select a folder of cars from the Products app. The template displays all cars from the selected folder.
  • sectionName to display in the navigation menu.

/one-pager-module/dialogs/components/content-items-list.yaml
 form:
  tabs:
    - name: tabText
      label: Texts
      fields:
        - name: title
          class: info.magnolia.ui.form.field.definition.TextFieldDefinition
          label: Title
        - name: sectionName
          class: info.magnolia.ui.form.field.definition.TextFieldDefinition
          label: Section nav label
          required: true
          requiredErrorMessage: Enter label for section navigation.
        - name: subText
          class: info.magnolia.ui.form.field.definition.RichTextFieldDefinition
          label: Sub title
    - name: contentSelectionTab
      label: Content items
      fields:
        - name: productFolderRef
          label: Select product folder
          required: true
          requiredErrorMessage: You must select a product item folder which contains a list of products!
          class: info.magnolia.ui.form.field.definition.LinkFieldDefinition
          targetWorkspace: products
          appName: products
          identifierToPathConverter:
            class: info.magnolia.ui.form.field.converter.BaseIdentifierToPathConverter

actions: !include /one-pager-module/includes/default-dialog-actions.yaml

Template script

The template script should do the following things:

  • Render the title and subText properties at the top of the component.
  • Iterate over the cars in the selected folder, rendering for each car:
    • Title
    • Description
    • Image and photo credit (copyright)

To understand what the script needs to output, have another look at the static HTML prototype:

prototype.html
<!-- starting with cars here ... -->
<div class="component-section" id="cars">
    <div class="container">
        <div class="row">
            <div class="col-lg-12 col-sm-12">
                <hr class="section-heading-spacer">
                <div class="clearfix"></div>
                <h2 class="section-heading">Classic cars</h2>
 
                <p class="lead">
 
                <p>Some of the most classic cars from U.S. and Great Britain.</p>
                </p>
            </div>
        </div>
 
        <div class="row cars">
            <div class="col-lg-12 col-sm-12">
 
                <!-- 1-car "repeatable" -->
                <div class="row car">
                    <div class="col-xs-6">
                        <div class="big-box">
                            <img class="img-responsive img-rounded" src="imgs/car-0_medium.jpg"/>
                        </div>
                        <div class="copyright">© Pedro Ribeiro Simões</div>
                    </div>
                    <div class="col-xs-6">
                        <div class="row">
                            <div class="col-xs-12"><h3>Riley Brooklands 1930</h3></div>
                            <div class="col-xs-12">
                                <p>The Riley Nine was one of the most successful light cars produced by the British motor industry
                                    in the inter war period. It was made by the Riley company of Coventry, England with a wide range
                                    of body styles between 1926 and 1938.</p>
 
                                <p>The car was largely designed by two of the Riley brothers, Percy and Stanley. Stanley was
                                    responsible for the chassis, suspension and body and the older Percy designed the engine.</p>
 
                                <p>The 1,087 cc four-cylinder engine had hemispherical combustion chambers with the valves
                                    inclined at 45 degrees in a crossflow head. To save the expense and complication of overhead
                                    camshafts, the valves were operated by two camshafts mounted high in the crankcase through short
                                    pushrods and rockers. The engine was mounted in the chassis by a rubber bushed bar that ran
                                    through the block with a further mount at the rear of the gearbox. Drive was to the rear wheels
                                    through a torque tube and spiral bevel live rear axle mounted on semi elliptic springs.</p>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-lg-12 col-sm-12">
                        <div class="between-car-spacer"></div>
                    </div>
                </div>
                <!-- /. -->
 
 
                <!-- 1-car "repeatable" -->
                <div class="row car">
                    <div class="col-xs-6">
                        <div class="big-box">
                            <img class="img-responsive img-rounded" src="imgs/car-1_medium.jpg"/>
                        </div>
                        <div class="copyright">© John Lloyd</div>
                    </div>
                    <div class="col-xs-6">
                        <div class="row">
                            <div class="col-xs-12"><h3>Pontiac Chieftain 1952</h3></div>
                            <div class="col-xs-12">
                                <p>The Pontiac Chieftain is an automobile that was produced by the Pontiac from 1949 to 1958.
                                    Chieftains were one of the first all new car designs to come to Pontiac in the post
                                    World War II years. Previous cars had been 1942 models with minor revisions.</p>
 
                                <p>The Chieftain was initially introduced with four models: Sedan, Sedan Coupe, Business Coupe
                                    and Deluxe Convertible Coupe. In 1950, a Catalina Coupe was added to the range while a station
                                    wagon was added in 1952, with the demise of the top of the line Streamliner wagon.</p>
 
                                <p>Some of the more interesting optional items available for the first generation Chieftain
                                    included a radio with seven vacuum tubes, tissue dispenser, under seat heaters, and a Remington
                                    Auto-Home shaver. In 1951, the horsepower on the 8-cylinder rose to 116. The Chieftain came with
                                    a gas gauge, ammeter, oil pressure gauge, and a temperature gauge which had marks for 160, 180,
                                    and 220 degrees Fahrenheit.</p>
 
                            </div>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-lg-12 col-sm-12">
                        <div class="between-car-spacer"></div>
                    </div>
                </div>
                <!-- /. -->
 
 
                <!-- 1-car "repeatable" -->
                <div class="row car">
                    <div class="col-xs-6">
                        <div class="big-box">
                            <img class="img-responsive img-rounded" src="imgs/car-2_medium.jpg"/>
                        </div>
                        <div class="copyright">© John Lloyd</div>
                    </div>
                    <div class="col-xs-6">
                        <div class="row">
                            <div class="col-xs-12"><h3>Continental Mark II</h3></div>
                            <div class="col-xs-12">
                                <p>The Continental Mark II is a personal luxury car that was produced by Continental in 1956
                                    and 1957. An attempt to build a post-World War II car to rival the greatest of the pre-War
                                    era, or anything produced in Europe, it is regarded as a rare and elegant classic.</p>
 
                                <p>Ford wanted a superior and standalone up-market brand – aside from Lincoln – to compete
                                    with General Motors' Cadillac, Packard, and Chrysler Corporation's Imperial brands.</p>
 
                                <p>The new Continental was not intended to be the largest or most powerful automobile; rather,
                                    the most luxurious and elegant American car available, designed to recapture the spirit of
                                    the great classics of the prewar period—with prices to match. The Mark II's inspiration
                                    was the celebrated V12-powered Lincoln Continental of the 1940s, among the most notable cars
                                    of that War-interrupted decade.</p>
 
                            </div>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-lg-12 col-sm-12">
                        <div class="between-car-spacer"></div>
                    </div>
                </div>
                <!-- /. -->
 
                <!-- 1-car "repeatable" -->
                <div class="row car">
                    <div class="col-xs-6">
                        <div class="big-box">
                            <img class="img-responsive img-rounded" src="imgs/car-3_medium.jpg"/>
                        </div>
                        <div class="copyright">© John Lloyd</div>
                    </div>
                    <div class="col-xs-6">
                        <div class="row">
                            <div class="col-xs-12"><h3>1927 Hudson</h3></div>
                            <div class="col-xs-12">
                                <p>The Hudson Motor Car Company made Hudson and other brand automobiles in Detroit, Michigan,
                                    from 1909 to 1954. In 1954, Hudson merged with Nash-Kelvinator Corporation to form American
                                    Motors (AMC). The Hudson name was continued through the 1957 model year, after which it
                                    was discontinued.</p>
 
                                <p>The company had a number of firsts for the auto industry; these included dual brakes, the
                                    use of dashboard oil-pressure and generator warning lights, and the first balanced crankshaft,
                                    which allowed the Hudson straight-six engine, dubbed the "Super Six" (1916), to work at
                                    a higher rotational speed while remaining smooth, developing more power for its size than
                                    lower-speed engines. The dual brake system used a secondary mechanical emergency brake system,
                                    which activated the rear brakes when the pedal traveled beyond the normal reach of the primary
                                    system; a mechanical parking brake was also used. Hudson transmissions also used an oil bath
                                    and cork clutch mechanism that proved to be as durable as it was smooth.</p>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-lg-12 col-sm-12">
                        <div class="between-car-spacer"></div>
                    </div>
                </div>
                <!-- /. -->
 
                <!-- 1-car "repeatable" -->
                <div class="row car">
                    <div class="col-xs-6">
                        <div class="big-box">
                            <img class="img-responsive img-rounded" src="imgs/car-4_medium.jpg"/>
                        </div>
                        <div class="copyright">© Pedro Ribeiro Simões</div>
                    </div>
                    <div class="col-xs-6">
                        <div class="row">
                            <div class="col-xs-12"><h3>Fiat Cinquecento</h3></div>
                            <div class="col-xs-12">
                                <p>The Fiat 500 (Italian: Cinquecento) was a city car produced by the Italian manufacturer
                                    Fiat between 1957 and 1975.</p>
 
                                <p>Launched as the Nuova (new) 500 in July 1957, it was a cheap and practical town car.
                                    Measuring only 2.97 metres (9 feet 9 inches) long, and originally powered by an appropriately
                                    sized 479 cc two-cylinder, air-cooled engine, the 500 redefined the term "small car" and
                                    is considered one of the first city cars.</p>
 
                                <p>Despite its diminutive size, the 500 proved to be an enormously practical and popular
                                    vehicle throughout Europe. Besides the two-door coupé, it was also available as the
                                    "Giardiniera" station wagon; this variant featured the standard engine laid on its side,
                                    the wheelbase lengthened by 10 cm (3.9 in) to provide a more convenient rear seat,
                                    a full-length sunroof, and larger brakes from the Fiat 600.</p>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-lg-12 col-sm-12">
                        <div class="between-car-spacer"></div>
                    </div>
                </div>
                <!-- /. -->
 
            </div>
        </div>
    </div>
</div>
<!-- eof: cars ... -->
Turning this into a FreeMarker script we end up with:
/one-pager-module/templates/components/content-items-list.ftl
 <div class="component-section" id="${content.@uuid}">
    <div class="container">
    [#--title, subText--]
        <div class="row">
            <div class="col-lg-12 col-sm-12">
                <hr class="section-heading-spacer">
                <div class="clearfix"></div>
                <h2 class="section-heading">${content.title!""}</h2>
            [#if content.subText?has_content]<p class="lead">${cmsfn.decode(content).subText}</p>[/#if]
            </div>
        </div>

        <div class="row cars">
            <div class="col-lg-12 col-sm-12">
            [#if content.productFolderRef??]
                [#assign productFolder = cmsfn.contentById(content.productFolderRef, "products")]
                [#if productFolder??]
                    [#assign productsList = cmsfn.children(productFolder, "mgnl:product")]
                    [#if productsList?has_content]
                        [#list productsList as product]
                            [#assign asset = damfn.getAsset(product.image!"") /]
                            [#if asset??]
                                [#assign productTitle = product.title!asset.title!asset.name /]
                                <div class="row car">
                                    <div class="col-xs-6">
                                        <div class="big-box">
                                            [#if product.image?has_content]
                                                [#assign imgRef = damfn.getAssetLink(product.image, "large")!]
                                                [#if imgRef?has_content]
                                                    <img class="img-responsive img-rounded" src="${imgRef}" alt="${productTitle!}">
                                                [/#if]
                                            [/#if]
                                        </div>
                                        [#if asset.getCopyright()?has_content]
                                            <div class="copyright">© ${asset.getCopyright()}</div>
                                        [/#if]
                                    </div>
                                    <div class="col-xs-6">
                                        <div class="row">
                                            [#if productTitle?has_content]
                                                <div class="col-xs-12"><h3>${productTitle}</h3></div>
                                            [/#if]
                                            [#if product.description?has_content]
                                                <div class="col-xs-12">${cmsfn.decode(product).description}</div>
                                            [/#if]
                                        </div>
                                    </div>
                                </div>
                                <div class="row">
                                    <div class="col-lg-12 col-sm-12">
                                        <div class="between-car-spacer"></div>
                                    </div>
                                </div>
                            [/#if]
                        [/#list]
                    [/#if]
                [/#if]
            [/#if]
            </div>
        </div>
    [#-- ./ row cars--]
    </div>
[#-- ./container --]
</div>
[#-- ./component-section --]
In the script we make heavy use of  cmsfn and  damfn  templating functions. They make common templating tasks such as creating links easier:

  • Line 16: cmsfn.contentById(content.productFolderRef, "products") gets the folder of cars the user selected. You can find the folder in the products  workspace using its unique ID (UUID) which is stored in the productFolderRef property.
  • Line 18: cmsfn.children(productFolder, "mgnl:product") builds a list of cars in the selected folder.
  • Line 21: damfn.getAsset(product.image!"") gets an asset from the Magnolia DAM. This is the car photo. It is linked to the car (product) by the image property.
  • Line 28: damfn.getAssetLink(product.image, "large") builds a hyperlink to the asset so we can display a car image on the page. We also pass a variation name large that you will create in Using a site definition.
  • Line 44: cmsfn.decode(product).description decodes content entered in the rich text field. See: Decode text.

Make the component available to the page template

Components are meant to be added to areas which are defined in a page template.

Edit the template definition of the page template main and make the new component available at the content-sections area:

one-pager-module/templates/pages/main.yaml
templateScript: /one-pager-module/templates/pages/main.ftl
renderType: freemarker
visible: true
title: One pager template
dialog: one-pager-module:pages/main
areas:
  content-sections:
    availableComponents:
      content-items-list:
        id: one-pager-module:components/content-items-list
Now you can use the component.

Add the component on the page

Add the new component on the page. In the dialog, select the /cars/classics folder from the Products app. Add another component using cars from the /cars/007 folder.

Added files overview

For this component you added the following files to the module:

 one-pager-module/
├── dialogs/
│   ├── components/
│   │   ├── content-items-list.yaml
└── templates/
    └── components/
        ├── content-items-list.ftl
        └── content-items-list.yaml


Next: Creating a text and image component

#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))