Cross Content


  1. Enable the following module: vactory_cross_content

  2. Visit : /admin/structure/types/manage/**content_type**

  3. Enable the cross content.

  1. Move to the Block Layout page.

  2. Inject the cross content block. Ensure that you select the one with the vactory category.

  1. Visit /block/add/vactory_block_component

  2. Create your custom cross content block, ensure that you have already created a dynamic field that will be displayed on the Next.js app to show your cross content items.

Here's a simple example :

./modules/custom/your_custom_module/widgets/cross-content-news/settings.yml

name: 'Cross content news'
multiple: FALSE
category: 'Cross Content'
enabled: TRUE
fields:
title:
type: text
label: "title"
intro:
type: text_format
label: "Introduction"
options:
"#format": full_html
link:
type: url_extended
label: "Link"
  1. Inject your cross-content custom block into the Footer region and ensure that you have configured the Visibility settings.

  2. On Next.js, you will need to create a mapping file.

./components/modules/news/CrossContentWidget.jsx

export const config = {
id: "vactory_news:cross-content-news",
}
const CrossContentNews = ({ data }) => {
console.log({data})
return <>News Cross Content</>
}
export default CrossContentNews
⚠️
Including the `vcc_normalized` field in the config constant is mandatory in your content type detail page file `**Node.jsx`.

./components/modules/news/NewsNode.jsx

export const config = {
id: "node--vactory_news",
params: {
fields: {
"node--vactory_news":
"vcc_normalized,title,body,field_vactory_excerpt,field_vactory_media,field_vactory_date",
"media--image": "thumbnail",
"file--image": "uri",
},
include: "field_vactory_media,field_vactory_media.thumbnail",
},
}

Now that we have included vcc_normalized to be retrieved along with the node fields data, the remaining step is to get the cross-content items from the node context.

For this we need to use the useNode custom hook.

You need to import the useNode from the hooks package.

./components/modules/news/CrossContentWidget.jsx

import { useNode } from "@vactorynext/core/hooks"

Congratulations! You have just displayed the cross content!

./components/modules/news/CrossContentWidget.jsx

import { useNode } from "@vactorynext/core/hooks"
export const config = {
id: "vactory_news:cross-content-news",
}
const CrossContentNews = ({ data }) => {
const { vcc } = useNode()
console.log({vcc})
return <>
{vcc?.map((item) => item?.title)}
</>
}
export default CrossContentNews
⚠️
You'll realize that the VCC constant only includes the node's title.

If you want to display additional information such as images, dates, or other details, what steps should you take ?

To address this problem, a new hook is implemented on the Drupal side called hook_jsonapi_vcc_normalized_node_alter(&$normalized_node, $context, $base_node_type). This hook allows developers to append additional information to vcc_normalized field.

Here's an example :

./modules/custom/your_custom_module/your_custom_module.module

function your_custom_module_jsonapi_vcc_normalized_node_alter(&$normalized_node, $context, $base_node_type) {
if ($base_node_type === 'vactory_news') {
$node = $context['node'];
$node_type = $context['node_type'];
if ($node_type === 'vactory_news') {
// Get image.
$lqipImageStyle = ImageStyle::load('lqip');
$output_field_name = 'field_vactory_media';
$mid = $node->get($output_field_name)->getString();
$result[$output_field_name] = NULL;
if (!empty($mid)) {
$mid = (int) $mid;
$media = Media::load($mid);
if (
$media &&
$media->bundle() === 'image' &&
isset($media->get('field_media_image')->getValue()[0]['target_id'])
) {
$fid = $media->get('field_media_image')->getValue()[0]['target_id'];
$file = File::load($fid);
if ($file != NULL) {
$uri = $file->getFileUri();
$fileResult = [];
$media_file_manager = \Drupal::service('vacory_decoupled.media_file_manager');
$fileResult['_default'] = $media_file_manager->getMediaAbsoluteUrl($uri);
$fileResult['_lqip'] = $media_file_manager->convertToMediaAbsoluteUrl($lqipImageStyle->buildUrl($uri));
$fileResult['uri'] = StreamWrapperManager::getTarget($uri);
$fileResult['fid'] = $fid;
$fileResult['file_name'] = $media->label();
$fileResult['meta'] = $media->get('field_media_image')
->first()
->getValue();
$result[$output_field_name] = $fileResult;
}
}
}
$normalized_node = [
'id' => $node->id(),
'image' => $result[$output_field_name],
'title' => $node->label(),
'excerpt' => $node->get('field_vactory_excerpt')->getValue(),
'url' => $node->toUrl()->toString(),
];
}
}
}