Can't get v-if to work in a custom block in the Panel

I’m creating a custom button block. The blueprint and snippet work perfectly in that I can enter the relevant fields and the button appears as intended in the front-end.

One of the blueprint fields is a toggles field for selecting alignment, with the chosen option adding an appropriate class. Although it works perfectly in the front-end, I want to be able to align the button in the Panel. For that, I’m trying to use a v-if conditional statement in the index.js file, But I can’t get it to work.

My index.js file looks like this…

panel.plugin("brandsistency/button-block", {
  blocks: {
    button: {
      template: `
        <button v-if="content.alignment === 'center'" class="txt-c" type="button" @click="open">{{ content.text }}</button>
        <button v-else-if="content.alignment === 'right'" class="txt-r" type="button" @click="open">{{ content.text }}</button>
        <button v-else type="button" @click="open">{{ content.text }}</button>
      `
    }
  }
});

The relevant section of the blueprint file looks like this…

alignment:
  type: toggles
  width: 1/2
  labels: false
  grow: false
  options:
    - value: center
      icon: text-center
    - value: right
      icon: text-right

If I choose center alignment and look in the page’s .txt file, there is a content>alignment>center sequence and the txt-c class does appear (from the snippet) in the button in the front-end. But if I look in the Panel, the button is there but the txt-c class is not added.

What is wrong with my index.js file? How do I get the relevant classes to add to the button in the Panel? I followed the guidance in the docs but I’m obviously missing something.

Frankly, I don’t think this is the right way to go about it. The only thing that differentiates your three buttons is the class you add to it (or don’t add to it).

So ideally, you have only one button element in your template, then use a method that returns the class name, and add that value to the class attribute.

Yes, that would be ideal, Sonja. And that’s the approach taken in the snippet – a single element with PHP if statements to add the relevant class. But I haven’t be able to work out how to make it work in the JS file for the Panel.

Not very much different in JS:

panel.plugin("brandsistency/button-block", {
  blocks: {
    button: {
      template: `
        <button :class="className" type="button" @click="open">{{ content.text }}</button>
      `,
      computed: {
        className() {
          let value = this.content.alignment;
          let className = value === 'center' ? 'txt-c' : value === 'right' ? 'txt-r' : '';
          return className;
        }
      },
    }
  }
});

BTW: We have quite a few examples in the guide: Page builder | Kirby CMS

Thanks, Sonja. That looks really promising. But on trying it, I think the issue I’m having is that my button block isn’t updating at all.

My index.js now looks very similar to your suggestion (I added a placeholder) but there is no change in the Panel. Even if I hardcode class="txt-c" into the <button> tag, when I look at Dev Tools in the Panel, all I see is the original…

<button type="button">text</button>

I updated the plugin version number in the composer.json file and that updated number shows up in the Panel’s System page. I’ve tried clearing cache, media folders, etc. but without success. It’s probably something obvious but I can’t figure out why the <button> tag isn’t updating in the Panel. Do I need to do something to force the plugin to use the latest version of index.js?

This is my latest index.js…

panel.plugin("brandsistency/button-block", {
  blocks: {
    button: {
      computed: {
        placeholder() {
          return "Button text...";
        },
        className() {
          let value = this.content.alignment;
          let className = value === 'center' ? 'txt-c' : value === 'right' ? 'txt-r' : ''; return className;
        }
      },
      template: `
        <button :class="className" type="button" @click="open">{{ content.text }}</button>
      `
    }
  }
});

For further clarification…

  • I have also created custom plugins to add center and right alignment buttons to the Writer field editing bar. They work perfectly in that the snippet adds “txt-c” and “txt-r” in the front-end and the index.js file also adds the classes in the Panel so they can be targeted via panel.css to align the text preview.

  • However, with this button-block plugin, the snippet successfully adds the alignment classes in the front-end but, no matter what changes I make to the index.js file, nothing happens to the button preview in the Panel.

    • The placeholder() instruction doesn’t work. If button text isn’t entered, the button preview remains empty. And because random spaces are added, the :empty styling in panel.css doesn’t work either because it doesn’t think the button is empty.
    • The Panel button always remains just <button type="button"> text </button>, even if I try to hardcode a class into the <button> in the template: section.
    • I reverted to an older, much simpler version of my index.js and tried hardcoding a class in that but still no change.

What am I getting wrong? Why are changes to index.js having no effect?

Not sure what the (caching?) issue was but I’ve (a) just got a new laptop and (b) rebuilt the button-block from scratch and my problem has been solved.