CPT ACF Agenda

1. Context
  • CPT UI: maakt het Custom Post Type “Agenda”.

  • ACF: voegt velden toe aan Agenda items:

    • datum (Date Picker)

    • starttijd (Time Picker)

    • eindtijd (Time Picker)

    • beschrijving (WYSIWYG editor)

    • ticket (URL)

    • afbeelding (Image)

  • Probleem: velden werden wél ingevuld in de editor, maar niet automatisch getoond in single of archive pagina’s.

  • Thema: Blocksy, geen Pro. Belangrijk: we wilden sidebar, styling en Customizer behouden.

2. Oplossing in stappen
Stap 1: Single pagina weergave
  • Functie agenda_velden_na_content voegt velden toe aan the_content alleen op single agenda-items (is_singular('agenda')).

  • Start- en eindtijd toegevoegd.

  • Labels (Datum:, Tijd:, Beschrijving:) vetgedrukt.

  • Afbeelding, ticket en beschrijving netjes gescheiden met spacing via CSS.

Stap 2: Archive / overzicht pagina
  • Functie agenda_velden_in_archief_content voegt velden toe in blog/archive loops.

  • Labels voor datum/tijd behouden, beschrijving label verwijderd.

  • Beschrijving ingekort tot 20 woorden.

Code en css gemaakt voor zowel cpt agenda archief, als losse pagina met shortcode. Ook code gemaakt om agenta items per maand te kunnen weergeven (vanuit sidebar; )

Stap 3: code voor child; functions.php + Css

// ===============================
// Agenda CPT
// ===============================

// Voeg ACF-velden toe aan archief en single via the_content filter
add_filter(’the_content’, function($content){
if( (is_post_type_archive(‘agenda’)
|| is_singular(‘agenda’)
|| is_tax()
|| is_home()
|| is_category()
|| is_tag())
&& get_post_type() === ‘agenda’
&& in_the_loop()
&& is_main_query()
){
$extra = ‘<div class=”agenda-info-loop”>’;
if($d = get_field(‘datum’)) $extra .= ‘<p><strong>Datum:</strong> ‘.esc_html($d).'</p>’;
$s = get_field(‘starttijd’); $e = get_field(‘eindtijd’);
if($s && $e) $extra .= ‘<p><strong>Tijd:</strong> ‘.esc_html($s).’ – ‘.esc_html($e).'</p>’;
elseif($s) $extra .= ‘<p><strong>Tijd:</strong> ‘.esc_html($s).'</p>’;
if($b = get_field(‘beschrijving’)) $extra .= ‘<div class=”agenda-beschrijving-loop”>’.wp_kses_post($b).'</div>’;
if($t = get_field(’ticket’)) $extra .= ‘<p><a href=”‘.esc_url($t).'” target=”_blank” class=”agenda-ticket”>Tickets</a></p>’;
if($a = get_field(‘afbeelding’)) $extra .= ‘<div class=”agenda-afbeelding”>’.wp_get_attachment_image($a, ‘medium’).'</div>’;
$extra .= ‘</div>’;
return $content.$extra;
}
return $content;
});

// Maandlijst shortcode
add_shortcode(‘agenda_maandlijst’, function() {
global $wpdb;
$base_url = is_post_type_archive(‘agenda’) ? get_post_type_archive_link(‘agenda’) : esc_url(add_query_arg([], home_url(add_query_arg([], $_SERVER[‘REQUEST_URI’]))));

$results = $wpdb->get_results(“
SELECT DISTINCT DATE_FORMAT(meta_value,’%Y-%m’) AS maand
FROM $wpdb->postmeta
INNER JOIN $wpdb->posts ON $wpdb->posts.ID=$wpdb->postmeta.post_id
WHERE $wpdb->postmeta.meta_key=’datum’
AND $wpdb->posts.post_type=’agenda’
AND $wpdb->posts.post_status=’publish’
ORDER BY maand ASC
“);

if ($results) {
echo ‘<div class=”agenda-maandlijst”><ul>’;
foreach ($results as $r) {
$ts = strtotime($r->maand . ‘-01’);
$label = ucfirst(date_i18n(‘F Y’, $ts));
$link = add_query_arg(‘agenda_maand’, $r->maand, $base_url);
echo ‘<li><a href=”‘ . esc_url($link) . ‘”>’ . esc_html($label) . ‘</a></li>’;
}
echo ‘</ul></div>’;
}
});

// Shortcode agenda items met maandfilter
add_shortcode(‘agenda_blocksy’, function($atts){
$atts = shortcode_atts([‘posts’=>10], $atts, ‘agenda_blocksy’);

$meta_query = [];
if(isset($_GET[‘agenda_maand’])) {
$m = sanitize_text_field($_GET[‘agenda_maand’]);
$meta_query[] = [
‘key’ => ‘datum’,
‘value’ => [$m.’-01′, date(‘Y-m-t’, strtotime($m.’-01′))],
‘compare’ => ‘BETWEEN’,
’type’ => ‘DATE’
];
}

$q = new WP_Query([
‘post_type’ => ‘agenda’,
‘posts_per_page’ => intval($atts[‘posts’]),
‘post_status’ => ‘publish’,
‘meta_query’ => $meta_query
]);

$out = ‘<div class=”agenda-archive-wrapper”>’;
if($q->have_posts()){
while($q->have_posts()){
$q->the_post();
$d = get_field(‘datum’); $s = get_field(‘starttijd’); $e = get_field(‘eindtijd’);
$b = get_field(‘beschrijving’); $t = get_field(’ticket’); $a = get_field(‘afbeelding’);

$out .= ‘<div class=”agenda-info-loop”><h3><a href=”‘.get_permalink().'”>’.get_the_title().'</a></h3><div class=”agenda-item-flex”>’;
$out .= ‘<div class=”agenda-afbeelding-col”>’;
$f = get_the_post_thumbnail(get_the_ID(),’medium’); if($f) $out .= $f;
if($a) $out .= wp_get_attachment_image($a,’medium’);
$out .= ‘</div><div class=”agenda-content-col”>’;
if($d) $out .= ‘<p><strong>Datum:</strong> ‘.esc_html($d).'</p>’;
if($s) $out .= ‘<p><strong>Tijd:</strong> ‘.esc_html($s).($e?’ – ‘.esc_html($e):”).'</p>’;
if($b) $out .= ‘<div class=”agenda-beschrijving-loop”>’.wp_kses_post($b).'</div>’;
if($t) $out .= ‘<p><a href=”‘.esc_url($t).'” target=”_blank” class=”agenda-ticket”>Tickets</a></p>’;
$out .= ‘</div></div></div>’;
}
wp_reset_postdata();
} else $out .= ‘<p>Geen agenda-items gevonden.</p>’;
$out .= ‘</div>’;

return $out;
});

// Filter maand voor CPT-archief
add_action(‘pre_get_posts’, function($query){
if(!is_admin() && $query->is_main_query() && is_post_type_archive(‘agenda’) && isset($_GET[‘agenda_maand’])){
$m = sanitize_text_field($_GET[‘agenda_maand’]);
$query->set(‘meta_query’, [[
‘key’ => ‘datum’,
‘value’ => [$m.’-01′, date(‘Y-m-t’, strtotime($m.’-01′))],
‘compare’ => ‘BETWEEN’,
’type’ => ‘DATE’
]]);
}
});

Css in customizer:

/* CSS voor single agenda item */
.agenda-info {
margin-top: 2em; /* afstand boven de hele box */
padding: 1.5em; /* binnenruimte van de box */
background: #fff; /* grijze achtergrond */
border-radius: 12px; /* afgeronde hoeken */
}

.agenda-info p {
margin: 0.5em 0; /* verticale ruimte tussen datum, tijd, ticket etc. */
}

.agenda-beschrijving {
margin-top: 1em; /* extra ruimte boven de beschrijving */
line-height: 1.6; /* regelhoogte voor betere leesbaarheid */
}

.agenda-ticket {
display: inline-block;
margin-top: 1em; /* ruimte boven ticket link */
padding: 0.5em 1em;
background: var(–theme-palette-color-2);
color: #fff;
border-radius: 6px;
text-decoration: none;
}

.agenda-ticket:hover {
background: var(–theme-palette-color-3);
}

.agenda-afbeelding {
margin-top: 1em; /* ruimte boven de afbeelding */
}

 

/* CSS voor overzicht / archief (blog grid, lijst, etc. */


.agenda-info-loop p,
.agenda-info-loop div {
margin: 0.4em 0;
}

.agenda-beschrijving-loop {
font-size: 0.9em;
line-height: 1.4;
}

.agenda-ticket {
display: inline-block;
margin-top: 1em;
padding: 0.4em 0.8em;
background: var(–theme-palette-color-2);
color: #fff;
border-radius: 4px;
text-decoration: none;
font-size: 0.9em;
}

.agenda-ticket:hover {
background: var(–theme-palette-color-3);
color: #fff;
}

.agenda-item-flex {
display: flex;
gap: 1.5em; /* ruimte tussen afbeelding en tekst */
align-items: flex-start;
margin-bottom: 2em; /* afstand tussen items */
flex-wrap: wrap; /* voor responsive */
}

.agenda-afbeelding-col {
flex: 0 0 200px; /* vaste breedte voor afbeelding */
}

.agenda-afbeelding-col img {
max-width: 100%;
height: auto;
display: block;
border-radius: 8px;
}

.agenda-content-col {
flex: 1; /* neemt de resterende ruimte in */
}

/* CPT agenda-item titel */
.agenda-info-loop h3 {
font-size: 1.6rem; /* pas de grootte aan naar wens */
font-weight: 500; /* iets minder dik dan standaard h3 */
margin-bottom: 0.5em; /* ruimte onder de titel */
line-height: 1.3; /* regelhoogte voor betere leesbaarheid */
}

/* Link in titel */
.agenda-info-loop h3 a {
color: var(–theme-palette-color-2); /* kleur van de link */
text-decoration: none; /* verwijder onderstreping */
}

.agenda-info-loop h3 a:hover {
color: var(–theme-palette-color-1); /* kleur bij hover */
}

/* Flex container van elk agenda-item */
.agenda-info-loop {
margin-bottom: 2.5em; /* grotere verticale ruimte tussen items */
padding-bottom: 1.5em; /* ruimte onder elk item voor scheidslijn */
border-bottom: 1px solid #e0e0e0; /* subtiele scheidslijn */
}

/* Laatste item geen scheidslijn */
.agenda-info-loop:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}

/* Flex wrapper: afbeelding + content */
.agenda-item-flex {
display: flex;
gap: 2em; /* horizontale ruimte tussen afbeelding en tekst vergroten */
align-items: flex-start;
flex-wrap: wrap; /* voor responsive */
}

 

Stap 4: Hoe we hier gekomen zijn
  1. ACF velden worden niet automatisch getoond in WordPress front-end → filteren via the_content.

  2. Single post: veld in detailpagina tonen met labels, spacing en styling.

  3. Archive / overzicht: apart filter voor loop, beschrijving label verwijderd en ingekort, start/eindtijd toegevoegd.

  4. Dubbele output opgelost: single functie enkel op is_singular('agenda'), archive functie enkel in loop.

  5. Spacing geregeld via CSS per context, zodat layout Blocksy intact blijft (sidebar, fonts, grid).