---
title: "Projects"
manual: "Academic Projects"
version: "main"
permalink: "https://docs.typo3.org/permalink/fgtclb/academic-projects:integrator-project-list@main"
source: "Integrator/ProjectList.rst"
rendered: "2026-10-26T19:20:38+00:00"
---

# Projects {#integrator-project-list}

![Icon of the Projects content element](../Images/Icons/projects.svg)

-   *CType:* `academicprojects_projectlist`
-   *Plugin:*

    `AcademicProjects`, plugin `ProjectList`, action
    `ProjectController::listAction()`

-   *Set:*

    `fgtclb/academic-projects-project-list`, included in
    `fgtclb/academic-projects`

-   *Templates:*

    `Templates/Project/List.html`, with the partials below
    `Partials/Project/`, see [Templates](https://docs.typo3.org/permalink/fgtclb/academic-projects:templates@main)

The **Projects** element shows the project pages below the pages an
editor chooses as cards: the project title, or the page title without one,
linked to the project page, the short description, the categories of the
project grouped by category type, and its first image. Above the cards the
visitor finds a sorting, one select per category type and a select for the
state of a project, and each change reloads the list with the new selection.
A list that finds nothing says "No projects found."

It is the element for the overview page of the projects of a faculty, an
institute or the whole institution. With the form hidden and the state preset
to **Active**, it shows the running projects on a landing page. To show
a few projects picked by hand, on the page of a research group for example,
use [Selected Projects](https://docs.typo3.org/permalink/fgtclb/academic-projects:integrator-project-list-single@main), which has the
same options.

![A form with sorting, category and active state selects above the number of projects found and a grid of project cards with title, state, short description and categories](../Images/Screenshots/project-list-default.png)

A project is a page of the page type **Academic project**. The list
finds these pages, not records in a folder, and links every card to the page.

The element renders the template `Project/List.html` with the partials
below `Project/`, among them `SortingAndFilters.html` for the form
and `Item.html` for a card. [The project list](https://docs.typo3.org/permalink/fgtclb/academic-projects:styling-list@main) and [A project](https://docs.typo3.org/permalink/fgtclb/academic-projects:styling-item@main)
show the markup, and [Templates](https://docs.typo3.org/permalink/fgtclb/academic-projects:templates@main) describes how to override the templates.
The list is rendered on every request rather than from the page cache, so the
selection of the visitor takes effect at once. A selection is part of the URL
and can be bookmarked or shared, see [Feature: Project filter selections have a URL](https://docs.typo3.org/permalink/fgtclb/academic-projects:feature-1790226101@main), and
[Route enhancers](https://docs.typo3.org/permalink/fgtclb/academic-projects:configuration-route-enhancers@main) turns it into a readable path. A sorting
or an active state the form does not offer, in the URL or in a submission, is
ignored, also a list of values where the form sends one. The default of the
extension applies in its place where the element shows that part of the form,
the preset of the element where it hides it.

Related chapters:

-   [The category filters](https://docs.typo3.org/permalink/fgtclb/academic-projects:configuration-list-filter@main) describes the site settings that decide
    which category filters the form offers.
-   [Active filters, reset link and result count](https://docs.typo3.org/permalink/fgtclb/academic-projects:configuration-active-filters@main) describes the active filter tags, the
    reset link and the number of projects found.
-   [The header of the content elements](https://docs.typo3.org/permalink/fgtclb/academic-projects:configuration-content-element-header@main) is for a site whose content
    element layout renders no header.
-   [Content Security Policy](https://docs.typo3.org/permalink/fgtclb/academic-projects:integrator-project-list-content-security-policy@main) explains how the
    form works under the Content Security Policy of TYPO3.

## Settings {#integrator-project-list-configuration}

The tab **Configuration** of the content element holds the options of
the list and, below them, the field that chooses the pages.

-   **Show active state options**

    -   *Type:* checkbox
    -   *Default:* on

    Shows the select **Active state**, with the options
    **All**, **Active** and **Completed**, in the form
    of the list. Switched off, the visitor cannot choose the state, and the list
    shows the state [Active state](https://docs.typo3.org/permalink/fgtclb/academic-projects:confval-project-list-active-state@main) presets.

    The option stores the inverse, `settings.hideActiveState`, which is why it
    reads "show" while the stored value hides. A template override checks
    `{settings.hideActiveState}`.

    With the select hidden, the list keeps the preset state when the visitor
    changes the sorting or a category, and whatever state the URL of a link
    carries. A list of running projects can therefore offer the category
    filter and still show only the running ones.

![The number of projects found above a grid of project cards, without any form](../Images/Screenshots/project-list-active-only.png)

-   **Active state**

    -   *Type:* select
    -   *Default:* All

    The state the list shows until the visitor picks another one:
    **All** projects, the **Active** ones or the
    **Completed** ones. [The state of a project](https://docs.typo3.org/permalink/fgtclb/academic-projects:configuration-active-state@main) describes
    which projects count as which. An empty or unknown value counts as
    **All**, and so does a list of values, which TypoScript makes of
    the setting as soon as it has a child. The state an element stores does
    not replace such a list.

![The Active state select set to Completed, a tag "Completed", a "Reset all filters" link, the number of projects found and the completed projects](../Images/Screenshots/project-list-filtered.png)

-   **Show filter options**

    -   *Type:* checkbox
    -   *Default:* on

    Shows one select per category type in the form, as the site settings of
    [The category filters](https://docs.typo3.org/permalink/fgtclb/academic-projects:configuration-list-filter@main) decide. Switched off, the visitor cannot
    filter by category, and the list shows what [Categories](https://docs.typo3.org/permalink/fgtclb/academic-projects:confval-project-list-categories@main) presets. The active filter tags of the categories
    are left out with the selects.

    The option stores the inverse, `settings.hideFilter`. With the category
    selects hidden, the list keeps the preset categories when the visitor
    changes the sorting or the state. Categories in the URL of a link narrow
    the list further and never replace a preset category. Without preset
    categories, such a link filters the list as before.

-   **Show sorting options**

    -   *Type:* checkbox
    -   *Default:* on

    Shows the two sorting selects, **Sorting field** and
    **Sorting direction**, in the form. Switched off, the list is
    sorted as [Sorting](https://docs.typo3.org/permalink/fgtclb/academic-projects:confval-project-list-sorting@main) says. With the sorting,
    the category filter and the state select all switched off, the element
    renders no form.

    The option stores the inverse, `settings.hideSorting`. With the sorting
    selects hidden, the list keeps the sorting chosen here when the visitor
    changes a category or the state, and whatever sorting the URL of a link
    carries.

-   **Sorting**

    -   *Type:* select
    -   *Default:* Title A-Z

    The order of the list until the visitor picks another one:

    -   **Title A-Z**, **Title Z-A**: by the title of the page.
        The cards show the project title where there is one, so a list sorted
        by title is out of order where the two differ.
    -   **Last updated (latest last)**,
        **Last updated (latest first)**: by the date in the field
        **Last Update** of the page properties, which an editor sets
        by hand.
    -   **Page sorting (Result may be unexpected)**,
        **Page sorting, reversed (Result may be unexpected)**: by the
        position of each page among its sibling pages. That is the order of the
        page tree only while all project pages share one parent page.
    -   **Budget (low to high)**, **Budget (high to low)**: by
        the project budget.
    -   **Start date (oldest first)**,
        **Start date (newest first)**: by the project start.

    Only the items of the select are supported. Any other value, an empty one,
    a field without a direction or a list of values for example, which the
    form never stores but an import or a TypoScript value for a content
    element without the field can produce, is ignored, and the list sorts by
    title, A to Z. TypoScript makes a list of the setting as soon as it has a
    child, such as
    `plugin.tx_academicprojects.settings.sorting.field`, also
    next to a value of the setting itself, and the sorting an element stores
    does not replace such a list, so every list the TypoScript applies to then
    sorts by title, A to Z. Remove the child, or replace the whole setting by a
    single value, to get the sorting of the element back.

-   **Categories**

    -   *Type:* category tree
    -   *Default:* empty

    Categories of the group `projects` the list is filtered by until the
    visitor selects categories of their own. A project has to carry every
    category selected here, so two categories of the same type find only the
    projects that carry both. A project that carries only a subcategory of a
    selected category is not found. Select at most one category per category
    type unless that is meant.

    The tree shows every category of the installation that belongs to a type
    of the group `projects`. While the category selects are shown, a selection
    the visitor submits replaces the categories chosen here of the category
    types the form offers, and the active filter tags show them as tags the
    visitor can remove. A category of a type the form does not offer, because
    [The category filters](https://docs.typo3.org/permalink/fgtclb/academic-projects:configuration-list-filter@main) leaves it out, stays. While the selects
    are hidden, the categories chosen here always apply.

-   **Show hidden records**

    -   *Type:* checkbox
    -   *Default:* off

    Lists hidden project pages as well, to every visitor, whatever the preview
    settings of the backend user say. Only the hidden state of a page is
    ignored: a start or end date, an access restriction to frontend user groups
    and a deleted page still keep a project out of the list. Use it for a list
    on an access restricted page that previews projects before they go online.

-   **Show active state badge**

    -   *Type:* checkbox
    -   *Default:* off

    Shows on every card whether the project is active or completed, see
    [The state on the project cards](https://docs.typo3.org/permalink/fgtclb/academic-projects:configuration-active-state-badge@main).

-   **Selected pages for startingpoints**

    -   *Type:* page
    -   *Default:* empty

    The pages the project pages sit in. The list shows the project pages that
    are direct subpages of one of the chosen pages. Project pages further down
    the page tree are not found, so choose every page or folder that holds
    projects. The form offers no **Recursive** field for this element.

    Empty, the list shows every project page of the installation, on every
    site. Only pages of the type **Academic project** are listed,
    whatever else lies below the chosen pages.

## The state of a project {#configuration-active-state}

A project is active while it has no end date or its end date is still ahead,
and completed once its end date has passed. The **Active state**
filter of the project lists selects by that rule, and a template reads the same
state from every project as `{project.activeState}`: `active` or
`completed`, never empty.

A project page whose end date was never stored has no end date either, and is
active. That is a page created in the page tree, a page switched to the project
page type, an imported page or one from before the extension was installed,
as long as no editor has entered an end date. The **Active** filter
lists it, and the **Completed** filter does not.

### The state on the project cards {#configuration-active-state-badge}

The option **Show active state badge** of the **Projects** and
the **Selected Projects** content elements shows the state on every
project card, with the labels `activeState.active` and
`activeState.completed` of this extension. It is off by default, and a
content element saved before the option existed stays without the badge.

The partial `Project/Item.html` renders it below the title:

```html
<p class="ace-state completed">Completed</p>
```

![A project card showing the title, the state "Active", the short description and the categories](../Images/Screenshots/project-list-state-badge.png)

An active project gets `active` instead. That class names the state in
every language, so a site styles the two states by it. A
site package with a `Project/Item.html` of its own shows the badge only
once it takes over that block.

## Two lists on one page {#integrator-project-list-two-lists}

All **Projects** elements of a page read the selection from the same
URL arguments. A submission of the form is answered by the first of them on
the page: it redirects to a URL that carries the selection as that element
sees it, the presets it keeps included. For another **Projects**
element of the page, a sorting or an active state the first element hides
replaces the one its visitor chose. The preset categories of category selects
the first element hides, and its preset categories of the category types its
form does not offer, are added to the categories the visitor chose. Put lists
whose forms hide or offer different parts on pages of their own.

## Content Security Policy {#integrator-project-list-content-security-policy}

The selects of the form submit it when the visitor changes one of them, through
the inline event handler `onchange="this.form.submit()"`. A nonce does not
cover an event handler attribute, so the frontend policy of TYPO3 blocks it
once a site enforces that policy. The extension therefore allows exactly this
handler text in its [`Configuration/ContentSecurityPolicies.php`](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/FileStructure/Configuration/ContentSecurityPolicies.html#file-extension-configuration-contentsecuritypolicies-php), which
TYPO3 loads on its own: the directive `script-src-attr` of the frontend policy
gets `'unsafe-hashes'` and
`'sha256-osjxnKEPL/pQJbFk1dKsF7PYFmTyMWGmVSiL9inhxJY='`. `script-src` is not
changed. Every site that inherits the default frontend policy gets both
sources. A site whose `csp.yaml` sets `inheritDefault: false`, and
a site package whose copy of `Project/DemandSorting.html`,
`Project/DemandCategories.html` or `Project/DemandActiveState.html` uses another handler text, add the
hash of that text in the `csp.yaml` of the site:

**config/sites/\<site>/csp.yaml**

```yaml
mutations:
  - mode: extend
    directive: 'script-src-attr'
    sources:
      - "'unsafe-hashes'"
      - "'sha256-osjxnKEPL/pQJbFk1dKsF7PYFmTyMWGmVSiL9inhxJY='"
```

The hash is the base64 encoded SHA-256 of the handler text, without the quotes
of the attribute. A policy the web server or a proxy sends is not covered and
needs the same sources itself.

A site whose policy allows inline scripts already, with `'unsafe-inline'` in
`script-src`, or in `default-src` where it has no `script-src`, gets no
`script-src-attr` from the extension: a listener of **academic_base**
takes it out again, unless the site declares the directive itself. The browser
then reads `script-src` for the handlers of the form, as for the site's own
handlers. On a page whose `script-src` keeps a nonce, a browser ignores
`'unsafe-inline'` and blocks both.

For a visitor without JavaScript the form renders a submit button inside
`<noscript>`, labelled `filter.submit`. A visitor with JavaScript
does not see it.

<!-- TODO: no Markdown rendering for "versionchanged" -->

The policy allows the handler, and the form renders the button.
