---
title: "ModifyBiteJobPostingsEvent"
manual: "Academic Bite Jobs"
version: "main"
permalink: "https://docs.typo3.org/permalink/fgtclb/academic-bite-jobs:developers-result-event@main"
source: "Developers/Events/ModifyBiteJobPostingsEvent.rst"
rendered: "2026-10-26T19:20:41+00:00"
---

<a id="developers-event-modify-bite-job-postings-event"></a>

# ModifyBiteJobPostingsEvent {#developers-result-event}

`\FGTCLB\AcademicBiteJobs\Event\ModifyBiteJobPostingsEvent` is owned by
this extension. A listener removes, changes, adds or enriches the postings the
job list renders.

## When it is dispatched {#developers-event-modify-bite-job-postings-event-dispatched}

The [Job List b-ite](https://docs.typo3.org/permalink/fgtclb/academic-bite-jobs:integrator-job-list-bite@main) dispatches the event each
time it renders, after the response of B-ITE is decoded and before
[Maximum number of job offers](https://docs.typo3.org/permalink/fgtclb/academic-bite-jobs:confval-job-list-bite-limit@main) is applied. It is
dispatched after a failed request as well, then with no postings and no response
data, so a listener does not need to know how the request went. The
[request event](https://docs.typo3.org/permalink/fgtclb/academic-bite-jobs:developers-event-modify-bite-job-postings-request-event@main)
comes before it.

## What a listener reads and changes {#developers-event-modify-bite-job-postings-event-api}

| Method | Returns |
| --- | --- |
| `getJobPostings()`, `setJobPostings()` | The postings the job list renders, a list with one array per posting as B-ITE answers it. The setter refuses anything else. |
| `getResponseData()` | The decoded response of the B-ITE API, or an empty array when the request failed or the response was not JSON. |
| `getSettings()` | The values stored below `settings.jobs` in the plugin settings of the content element, as in the request event. |
| `getRequest()` | The request of the page being rendered. |
| `getPluginControllerActionContext()` | The context of the job list that asked, as in the request event. |

The limit of the content element is applied to the postings the listeners hand
back, so a listener sees every posting of the response and the job list never
renders more than the limit.

## Example: a grouping by a custom field {#developers-example-grouping}

The second half of the [custom field example](https://docs.typo3.org/permalink/fgtclb/academic-bite-jobs:developers-example@main)
writes the name of the relation into every posting, so the job list can group
by it:

**EXT:my_extension/Classes/EventListener/NameTheRelationOfEveryJob.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\EventListener;

use FGTCLB\AcademicBiteJobs\Event\ModifyBiteJobPostingsEvent;
use TYPO3\CMS\Core\Attribute\AsEventListener;

final class NameTheRelationOfEveryJob
{
    private const RELATION_NAMES = [
        '01' => 'Appointment procedures',
        '02' => 'Academic staff',
        '03' => 'Non-scientific staff',
        '04' => 'Training positions',
    ];

    #[AsEventListener(identifier: 'my-extension/name-the-relation-of-every-job')]
    public function __invoke(ModifyBiteJobPostingsEvent $event): void
    {
        $jobs = $event->getJobPostings();
        foreach ($jobs as $index => $job) {
            $relation = (string)($job['custom']['zuordnung'] ?? '');
            $jobs[$index]['relationName'] = self::RELATION_NAMES[$relation] ?? '';
        }
        $event->setJobPostings($jobs);
    }
}
```

The grouping itself is TypoScript, see [Grouping the jobs](https://docs.typo3.org/permalink/fgtclb/academic-bite-jobs:configuration-general-group-by@main):

**TypoScript setup**

```typoscript
plugin.tx_academicbitejobs.settings.jobs.groupBy = relationName
```

Where the custom field sits in a posting, and which values it has, depends on
how it is set up in B-ITE, so read one response of your job listing before
relying on the path above. A listener that needs the labels of the values can
ask the options API of B-ITE for them.

## Rules and pitfalls {#developers-event-modify-bite-job-postings-event-rules}

**Hand back a list.** `setJobPostings()` throws an
`\InvalidArgumentException` for an array that is not keyed from `0`
without gaps, or for a posting that is not an array. A listener that removes
postings with `array_filter()` passes the result through
`array_values()`.

**The templates read the keys B-ITE answers with.** The views show the `title`,
the `url` and the `endsOn` of a posting. A posting a listener adds needs them
too, and a value a listener adds appears only where a template override or the
grouping reads it.

The rules both events share are on the [overview page](https://docs.typo3.org/permalink/fgtclb/academic-bite-jobs:developers-rules@main).

## Introduced in {#developers-event-modify-bite-job-postings-event-introduced}

-   [Feature: Request and result events for the B-ITE job list](https://docs.typo3.org/permalink/fgtclb/academic-bite-jobs:feature-1790774401@main): the event, in version 2.4.
-   [Breaking: The B-ITE jobs controller is final](https://docs.typo3.org/permalink/fgtclb/academic-bite-jobs:breaking-1791043409@main): the controller is final, a project changes the
    postings with this event instead of a subclass.
