Access Object Data via KQL

Hi,

pretty new to Kirby and already with a fairly complex setup as it seems. I am using Kirby headless with the KQL Plugin. Astro JS in the frontend.

My content is based on custom blocks. One of the blocks is a list of links. Links can be internal (pages), files or external (url).
I am using a structure field with an object field inside to have the options for link label and target. Blueprint looks like this:

name: Links
icon: dots
fields:
  links:
    label: Links
    type: structure
    sortable: true
    fields:
      linkdata:
        label: Link
        type: object
        fields:
          link:
            type: link
            options:
              - page
              - url
              - file
          label:
            label: Beschriftung
            type: text
          target:
            label: Ziel
            type: toggle
            text: In neuem Fenster öffen?

My current problem is the conversion of a page type link to a relative url / path. My fetch request body / query looks like this. “blocks” beeing a blocks-type field called “content” (might need to finalise naming here later :grimacing:)

"blocks": {
        "query": "page.content.content.toBlocks",
		"select": {
			"type": true,
			"content": true,
			"image": {
				"query": "block.image.toFile",
				"select": {
					"file": "file",
					"srcset": "file.srcset('default')",
					"src": "file.resize(32)"
				}
			},
			"links": {
				"query": "block.links.toStructure",
				"select": {
					"id": true,
					"linkdata": {
	"query": "structureItem.linkdata.toObject",
	"select": {
		"target": true,
		"link": true
	}
}
				}
			}
		}
     }

Response (only the “links” part) looks like this:

"links": [
	{
		"id": "0",
		"linkdata": {
			"target": "false",
			"link": "page:\/\/mdoFSpOhgxZbZt2B"
		}
	}
]

How do i convert the “link” to a relative url? I tried something like this in the query:

"linkdata": {
	"query": "structureItem.linkdata.toObject",
	"select": {
		"target": true,
		"link": "objectItem.link.toPage"
	}
}

Basically inspired by the “structureItem”-method.
The idea was to have the page data and work from there. but i get a “Access to non-existing property "objectItem" on array”.

Any help or hints much appreciated!

Have you tried item instead of objectItem?

Just tried it. Same result unfortunately:
“Access to non-existing property "item" on array”.

I also just tried “arrayItem”. Same result.

Hm, unfortunately, I’m not really familiar with KQL. I know there are some headless Starterkit lying around based on KQL, maybe something like this here: Starter Kits | nuxt-kql

Don’t think it helps with the actual problem, but takes a different approach.

No problem. Thanks for your help anyways!
I already had a look at the Nuxt Starterkit digging around in the code for any hints but without any luck yet.
I will skip this part in development for now and cross fingers for some KQL-Expert to come around.
Otherwise i could still open up an issue on the KQL Github Repo i guess.

@earl You can access nested data from object fields as follows. The key here is to use content. Unfortunately, objectItem won’t work. Dunno why.

import type { KirbyQuerySchema } from 'kirby-types'

export const siteQuery: KirbyQuerySchema = {
  myObjectField: {
    query: 'site.myObjectField.toObject',
    select: {
      title: true,
      image: {
        query: 'content.image.toFile',
        select: {
          alt: true,
          srcset: 'file?.srcset',
          url: 'file?.crop(1920, 640)?.url',
        },
      },
    },
  },
}

@earl Regarding resolving data inside of blocks, you have to use a custom blocks resolver that transforms Kirby blocks data on the fly. This is available in the Kirby Headless plugin.

The KQL plugin proxies Kirby classes to “interceptor” classes which define what methods are available or not.

toObject() returns an object of class Kirby\Content\Content which is then proxied by KQL to Kirby\Kql\Interceptors\Content\Content.

You need to use content, because that’s the “class alias” defined for that class: