Problem

Atm the JSON serialization is not 100% clear on what's a slot or prop. Example take the following example JSON

              {
                "element": "teaser-wide",
                "type": "article",
                "href": "/blog/drupal-dev-days-2025-innovation-community-und-zusammenarbeit-224",
                "title": "Drupal Dev Days 2025: Innovation, Community und Zusammenarbeit in Leuven ",
                "heroType": "image",
                "category": "Drupal Dev Days",
                "author": "Wolfgang Ziegler",
                "excerpt": "Drupal-Innovation beschleunigt sich! Begleiten Sie uns auf unserer Reise zu den Drupal Dev Days 2025 in Leuven, wo wir ambitionierte Pläne für den Experience Builder, KI-Integration und eine neue europaweite Drupal-Vereinigung geschmiedet haben und dabei den Austausch mit der engagierten Drupal-Community pflegten.",
                "image": {
                  "aspectRatio": 133.33,
                  "src": "https://cp.drunomics.com/files/styles/300_225/public/2025-05/ddd_group_photo.jpg?itok=WPFebnk6&focal_point=40151dc2",
                  "srcset": null,
                  "alt": "Group photo at Drupal Dev Days Leuven",
                  "title": "© Joris Vercammen, borisson_"
                },
                "publishedAt": "05. Mai 2025"
              }

It's hard to tell whether "image" is a prop with an array/object value or a slotted element. The existence of the "element" property is a good guess, but not 100% clear since a prop arrray/object can also have it.

However, we should provide and need a 100% way to identify slots/props to easily pass the data the right way to components.

Proposed resolution

As prototyped at https://github.com/drunomics/nuxtjs-drupal-ce/pull/402:

The idea is to add explicit "props" and "slots" keys:

{
  "element": "teaser-wide",
  "props": {
    "type": "article",
    "href": "/blog/drupal-dev-days-2025-innovation-community-und-zusammenarbeit-224",
    "title": "Drupal Dev Days 2025: Innovation, Community und Zusammenarbeit in Leuven ",
    "heroType": "image",
    "category": "Drupal Dev Days",
    "author": "Wolfgang Ziegler",
    "excerpt": "Drupal-Innovation beschleunigt sich! Begleiten Sie uns auf unserer Reise zu den Drupal Dev Days 2025 in Leuven, wo wir ambitionierte Pläne für den Experience Builder, KI-Integration und eine neue europaweite Drupal-Vereinigung geschmiedet haben und dabei den Austausch mit der engagierten Drupal-Community pflegten.",
    "image": {
      "aspectRatio": 133.33,
      "src": "https://cp.drunomics.com/files/styles/300_225/public/2025-05/ddd_group_photo.jpg?itok=WPFebnk6&focal_point=40151dc2",
      "srcset": null,
      "alt": "Group photo at Drupal Dev Days Leuven",
      "title": "© Joris Vercammen, borisson_"
    },
    "publishedAt": "05. Mai 2025"
  },
  "slots": {
    "slotname1": "slot string"
  }
}
}

API change

Obviously the new API format would be a breaking change. We could make using it configurable, default to the new "explicit" format for new installs, keep existing install at the "legacy" format and keep supporting it until the next major version of the release.

Outcome

It will allow us to simplify slot-handling in the frontend, e.g. we could simply work with vanilla slots like the following. Taking the example from "Getting started" docs:

Before

<template>
  <div class="teaser-listing">
    <h2>Title: {{ title }}</h2>
    <slot>
      <component :is="useDrupalCe().renderCustomElements(content)" />
    </slot>
  </div>
</template>

<script setup lang="ts">
  defineSlots<{
    default(): any;
  }>();
  defineProps<{
    title: string;
    content?: CustomElementContent;
  }>();
</script>

After

<template>
  <div class="teaser-listing">
    <h2>Title: {{ title }}</h2>
    <slot>
    </slot>
  </div>
</template>

<script setup lang="ts">
  defineSlots<{
    default(): any;
  }>();
  defineProps<{
    title: string;
  }>();
</script>
Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

fago created an issue. See original summary.

fago’s picture

Issue summary: View changes
fago’s picture

Issue summary: View changes
fago’s picture

Issue summary: View changes
fago’s picture

Since our custom element class uses attributes terminology, not props, the question is what we should use here.

Overall usage:
- Custom Elements spec: "attributes" (string-only) vs "properties" (any type)
- React: "props"
- Vue: "props" (component data) vs "attrs" passed (HTML attributes)

More important, the Web Components Terminology Distinction

Attributes (HTML):
- String-only values
- Set via HTML:
- Retrieved via: element.getAttribute('title')

Properties (JavaScript):
- Any JavaScript type (objects, arrays, etc.)
- Set via JavaScript: element.imageData = {src: '...', alt: '...'}
- Retrieved via: element.imageData

--> in our case, the values may be objects, like imagedata, not only strings. So I think going with props instead of attributes makes sense + it fits the JS-world well.

fago’s picture

Version: 3.2.0 » 3.x-dev
Priority: Normal » Major
Issue summary: View changes

frontend PR https://github.com/drunomics/nuxtjs-drupal-ce/pull/402 is ready for review. it's backward compatible

  • fago committed 8fd5a257 on 3.x
    [#3555044] feat: Add new explicit JSON output to differentiate between...
fago’s picture

Status: Active » Fixed

Feedback on this change was overall positive, so let's move on and merge this for easier testing.

Changes are backwards compatible, existing install will stay on legacy format. Changes come with a new settings form. New installs will have explicit format enabled by default.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.