No text when fetching page text via Kirby API

I followed the cookbook recipe for creating additional block types and have a problem with the card block.
When I select an existing page as the card type it picks up the cover image and the heading text but the description text always returns with a “No text value” information.
I would like to use the content of the created “intro” field or an excerpt of the “content” field here but I don’t know how to do this. I guess it will be added either in the card.php or the index.js part!?

You have to make sure to fetch the correct field name in index.js

Where exactly do I do it?
I cannot find the correct line for defining it in this part:

computed: {
          cardType() {
            return this.content.cardtype;
          },
          heading() {
            return (this.cardType === 'manual') ? this.content.heading : this.page.text;
          },
          image() {
            if(this.cardType === 'manual') {
              return this.content.image[0] || {};
            } else {
              return this.page.image || {}
            }
          },
          pageId() {
            return this.page ? this.page.id : '';
          },
          page() {
              return this.content.page[0] || {};
          },
        },
        watch: {
          "cardType": {
            handler (value) {
             if(value === 'page' && this.pageId) {
              this.$api.get('pages/' + this.pageId.replace('/', '+')).then(page => {
                this.text = page.content.text.replace(/(<([^>]+)>)/gi, "") || this.text;
              });
             } else if(value === 'manual') {
               this.text = this.content.text || this.text;
             }
  
            },
            immediate: true
          },
          "page": {
            handler (value) {
             if(this.cardType === 'page' && this.pageId) {
              this.$api.get('pages/' + this.pageId.replace('/', '+')).then(page => {
                this.text = page.content.text.replace(/(<([^>]+)>)/gi, "") || this.text;
              });
             } else if(value === 'manual') {
               this.text = this.content.text || this.text;
             }
            },
            immediate: true
          }

The heading seems to be taken by this.page.text but I would expect this.page.title and the {{ text }} definition isn’t visible for me. I would like to set it to “intro” or “text” field.

In both watchers (cardType and page), a field called text is fetched, so you would have to replace this with your field name

I have already tried it with several variations but cannot make it work (because I don’t fully understand the logic):

The page text field it should grab is called “intro” or if this one is empty it should use an excerpt of the page field “text”.
All of these solutions don’t work:

this.text = page.text.replace(/(<([^>]+)>)/gi, "") || this.text;
this.text = page.text.text.replace(/(<([^>]+)>)/gi, "") || this.text;
this.text = page.content.intro.replace(/(<([^>]+)>)/gi, "") || this.text;

Even the text of @texnixe recipe returns this error:

Uncaught (in promise) TypeError: page.content.text.replace is not a function

Might be because you are using 3.6 alpha, I still have my working example running in 3.5 and the whole field with the examples currently only gives me an error.

Hmm, could be the reason indeed.
At least all the other custom blocks work with Kirby 3.6 and the card block also to 90%, but just the text part seems to fail for existing pages.

Hm, I deleted all text, and now it also works in 3.6 alpha. Even with a different field name, e.g. intro.

 watch: {
        "cardType": {
          handler (value) {
           if(value === 'page' && this.pageId) {
            this.$api.get('pages/' + this.pageId.replace('/', '+')).then(page => {
              this.text = page.content.intro.replace(/(<([^>]+)>)/gi, "") || this.text;
            });
           } else if(value === 'manual') {
             this.text = this.content.text || this.text;
           }

          },
          immediate: true
        },
        "page": {
          handler (value) {
           if(this.cardType === 'page' && this.pageId) {
            this.$api.get('pages/' + this.pageId.replace('/', '+')).then(page => {
              this.text = page.content.intro.replace(/(<([^>]+)>)/gi, "") || this.text;
            });
           } else if(value === 'manual') {
             this.text = this.content.text || this.text;
           }
          },
          immediate: true
        }
      },
1 Like

Yeah, you are right, thanks.
I tested it again and first it didn’t work but then I cleared the cache and it worked (I thought using this prevents caching).
How could I extend that to

IF intro empty THEN excerpt of text (and text is a blocks text field which needs to be converted to plain text first)

I don’t know what is a good way to get an excerpt of a blocks field, no matter if you get this in JS or PHP via a custom api endpoint. That very much depends on what content you have there, maybe fetch a text block and short it.

How could I fetch the first text block there?

This should work:

page.content.text[0]['content'].text

Do a console.log() to always examine what you get step by step so you know what to fetch

Thanks a lot, it works but the formatting doesn’t look nice (no space after a sentence), especially with links:

Where can I find a documentation about the required skills to improve this?

I also tried to combine it with a check for intro field not empty, else show text field content but failed:

this.text = if(page.content.intro){page.content.intro.replace(/(<([^>]+)>)/gi, "")} else page.content.text[0]['content'].text.replace(/(<([^>]+)>)/gi, "") || this.text;