Custom field - Empty prop

Hello,

I’m still working on custom form plugin for the panel and I’m stuck on this : I try to get image from the page then display it and create DIV over it (comics balloons)

Here’s my php :

<?php
Kirby::plugin('gdt/case', [
	'fields' => [
        'case' => [
            'props' => [
                'image' => function ($image = null) {
                    $img = $this->formFields()->chapter_page_image()->value()[0];
                    var_dump($img); //gives a perfecr result
                    return $img; //Undefined array key 0 in file: .../gdt-case/index.php line: 7
                }               
            ]
        ]
    ]
]);

When I dump my $img var in php, it shows what I expect :

Array
(
    [id] => la-circulation-sanguine/au-coeur-du-sujet/grandiloquents-e1c1_2022_1.jpg
    [image] => Array
        (
            [back] => pattern
            [color] => orange-400
            [cover] => 
            [icon] => image
            [ratio] => 3/2
            [url] => http://localhost/grandiloquents/media/pages/la-circulation-sanguine/au-coeur-du-sujet/60b5886ede-1670931564/grandiloquents-e1c1_2022_1.jpg
            [src] => data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw
            [srcset] => http://localhost/grandiloquents/media/pages/la-circulation-sanguine/au-coeur-du-sujet/60b5886ede-1670931564/grandiloquents-e1c1-2022-1-352x.jpg 352w, http://localhost/grandiloquents/media/pages/la-circulation-sanguine/au-coeur-du-sujet/60b5886ede-1670931564/grandiloquents-e1c1-2022-1-864x.jpg 864w, http://localhost/grandiloquents/media/pages/la-circulation-sanguine/au-coeur-du-sujet/60b5886ede-1670931564/grandiloquents-e1c1-2022-1-1408x.jpg 1408w
        )

    [info] => 
    [link] => /pages/la-circulation-sanguine+au-coeur-du-sujet/files/grandiloquents-e1c1_2022_1.jpg
    [sortable] => 1
    [text] => grandiloquents-e1c1_2022_1.jpg
    [uuid] => file://NJxWw4F9LNEI2ZGq
    [filename] => grandiloquents-e1c1_2022_1.jpg
    [dragText] => (image: grandiloquents-e1c1_2022_1.jpg)
    [type] => image
    [url] => http://localhost/grandiloquents/media/pages/la-circulation-sanguine/au-coeur-du-sujet/60b5886ede-1670931564/grandiloquents-e1c1_2022_1.jpg
)

but in Vue component, a simple console.log() return an empty array and using it in the template throw me an error : Undefined array key 0 in file: …/site/plugins/gdt-case/index.php line: 7

Some has any clue about that ?

Thanks a lot !

Trying to understand what you are doing there. I guess you want to create a field that listens to the value of another field as this changes.

For one thing, the props are not the right place to do this, their purpose is to define the field options, so you would need a computed value. But still, when the page is created, your image field will be empty and you will get an error anyway.

However, if I am correct and you want to fetch the image as it changes, before the page is ever saved. This can only be done on the client side, in your Vue component.

Thanks texnixe,

indeed I try to get the image from the sibling field. Real-time is an great enhancement but not necessary.

So clearly speaking, I try to get the image stored in the field next to mine (at least url) then I can work over it in my vue component and save coordnates.

My goal is not to transform the image but just displaying it as a background to draw coordnates over it.

In Vue app I would have pass this in props.

Thanks for your reply

What you can do

<?php
Kirby::plugin('gdt/case', [
	'fields' => [
        'case' => [
            'computed' => [
                'url' => function () {
                    return $this->model()->chapter_page_image()?->url();
                },
            ],
        ]
    ]
]);

Then in your Vue part:

panel.plugin('gdt/case', {
  fields: {
    case: {
      props: {
        url: String
      },
      template: `<template>
          <div>
          <k-aspect-ratio
          class="k-whatever"
          cover="true"
          ratio="1/1"
        >
          <img
            v-if="url"
            :src="url"
            alt=""
          >
        </k-aspect-ratio>
          </div>
        </template>`
    }
  }
});

but the downside of this approach is that the image won’t change when you change the image, and you need to reload the page after selecting your image for the first time, because the PHP part happens server-side and has no knowledge about what’s going on in your frontend.

Thanks so much, I’ll try that !

Hi,

and of course happy new year ! Long live kirby.

The fact is that, even with computed I get an empty result in vue.js component. (In php it’s still the good result…)

Any other clue ?

Have a good day.

No. But you should post your full code to enable us to reproduce your issue. I tested the code above before posting it here. Also make sure that your field name is correct.

Thanks a lot for your time,

as previously said :

  • with static content like ‘foo’ everything works perfectly. I can get properly, my computed or prop items. I can even get data from blueprint (as custom label for example)
  • Var dump works well in php and gives images url… (before vuejs)
    → still can’t obtain nothing but an empty array in my vue.js component…

And unfortunately, the result is the same with the code you proposed… :slightly_frowning_face:


Here is my blueprint :

chapter_pages:

      label: Chapter pages
      type: structure
      fields: 
        chapter_page_transition:
          ...
        chapter_page_transition_url:
         ...
        chapter_page_transition_fade_type:
          ...
        chapter_page_transition_fade_speed:
          ...
        chapter_page_image:
          label: Image
          type: files
          layout: cards
          multiple: false
        chapter_page_case:
          type: case
          label: Draw ballons over the image
        chapter_page_balloons:
          label: Balloons
          type: structure
          fields:
            chapter_page_balloon_text:
              label: Text
              type: writer
            chapter_page_balloon_xstart:
              label: Start Horizontal
              type: number
              width: 1/4
              chapter_page_balloon_ystart:
                label: Start Vertical
                type: number
                width: 1/4
              chapter_page_balloon_xend:
                label: End Horizontal
                type: number
                width: 1/4
              chapter_page_balloon_yend:
                label: End Vertical
                type: number
                width: 1/4

Here is my Php :

<?php
Kirby::plugin('gdt/case', [
	'fields' => [
        'case' => [
            'computed' => [
                'url' => function () {
                    $img = $this->formFields()->chapter_page_image()->value();
                    return $img[0]['image']['url'];
                }               
            ]
        ]
    ]
]);

The index.js

import Case from "./components/fields/Case.vue";

panel.plugin("gdt/case", {
	fields: {
		case: Case
	},
});

And here is a simpler version of my Vue component

<template>
	<div>
		<k-field class="k-case-field" :label="label">

				<img
					v-if="url"
					:src="url" alt=""
					ref="image"
					@load="init()"
				/>

		</k-field>
  </div>
</template>

<script>
export default {
	props: {
		label: String,
		url: String	
	},
	mounted(){
		console.log(this.url)
		this.init()
	},
	methods: {
		init(){
			//doSomething...
		},
		
    }
  }
</script>

I’m a bit disoriented…

Thanks a lot and have a nice day !

Gauthier

Ah, ok, you do it differently via the formfields, probably because your fields live inside a structure field, so you would have to fetch the image of the the same structure field item, hm…

Yes, exaclty

I think I would pass the structure field to the frontend, then try to take it from there.

Thanks for you reply,

do you have a little example of how you would do it ?

Have a good day,

Maybe it’s even easier and you don’t need a prop.

panel.plugin('gdt/case', {
  fields: {
    case: {
      props: {
        formData: {
          type: Object,
          default() {
            return {};
          }
        },
      },
      mounted(){

        console.log(this.formData.myimage[0].url); //myimage is the fieldname for the image in my test example

      },
      template: `<template>
          <div>
          <k-aspect-ratio
          class="k-block-type-audio-poster"
          cover="true"
          ratio="1/1"
        >
          <img
            v-if="url"
            :src="url"
            alt=""
          >
        </k-aspect-ratio>
          </div>
        </template>`
    }
  }
});

Oh yeah ! It works ! Thanks a lot for that :slight_smile: It’ll make my day.

Have a nice one !