Extending nested panel components not possible

I am trying to customize parts of the pages section. To do so, want to extend components that are used in k-pages-section, e.g. k-empty. In my test case is also a files section included.

# Blueprint
title: Test
sections:
  pages_section:
    headline: Pages Section
    type: pages
  files_section:
    headline: Files Section
    type: files

To extend the components is no problem.

// index.js
panel.plugin('my/plugin', {
    components: {
        'k-empty': {
            extends: 'k-empty',
            template: `<p>lalala</p>`
        },
        'k-headline': {
            extends: 'k-headline',
            template: `<p>headline</p>`
        }
    },
});

Instead of the original template “lalala” and “headline” are displayed.

section-overwritten

But when I want to extend the pages section at the same time, the other component changes are ignored inside the pages section.

// index.js
panel.plugin('my/plugin', {
    components: {
        'k-empty': {
            extends: 'k-empty',
            template: `<p>lalala</p>`
        },
        'k-headline': {
            extends: 'k-headline',
            template: `<p>headline</p>`
        },
        'k-pages-section': {
            extends: 'k-pages-section'
        }
    },
});
  • empty and headline for the files section are correctly overwritten. But not for the pages section.
  • changing the order of extended components (e.g. extend k-pages-section first) has no effect.

Console Output:

Plugin is replacing "k-empty" app.js:1:236187
Plugin is replacing "k-headline" app.js:1:236187
Plugin is replacing "k-pages-section" app.js:1:236187

It looks like components nested inside the pages section are not overwritten…why?

1 Like

Sounds like a bug to me. Could you please open an issue on GitHub?

Thanks :slight_smile:

1 Like

Depending on whether you actually need to extend k-empty and k-headline; if you don’t, you might get away with something like this:

// index.js
const empty = {
  template: `<p>lalala</p>`
};

const headline = {
  template: `<p>headline</p>`
};


panel.plugin('my/plugin', {
  components: {
    'k-pages-section': {
      extends: 'k-pages-section',
      components: {
        'k-empty': empty,
        'k-headline': headline
      }
    }
  },
});

This way you override the components only for the pages section, which isn’t necessarily bad if what you want is to “customize parts of the pages section”.

If you need to also extend (and not only override) k-empty and k-headline it becomes more complicated

1 Like

That’s an excellent solution to redefine components locally.

I am still looking for a solution to extend them. E.g. If I wanted to adjust the page create dialog only in my custom pages section, I’ll have to copy a lot of code.

I guess you need to either wait for this to be fixed or go the “differently supported” way:


// index.js
const empty = {
  mounted: function() {
    console.log('Hello');
  }
};

const headline = {
  mounted: function () {
    console.log('World');
  }
};

const pages = {
  mounted: function() {
    console.log('extending stuff like a pro here')
  },
  components: {
    'k-empty': empty,
    'k-headline': headline
  }
}

panel.plugin('my/plugin', {
  use: [
    function(Vue) {
      empty.extends = Vue.options.components['k-empty'];
      headline.extends = Vue.options.components['k-headline'];
      pages.extends = Vue.options.components['k-pages-section'];

      Vue.component('k-pages-section', pages);
    }
  ],
});

try this.

Everything will look normal (because you extend the components), but you’ll see from the console that your components are actually used. (I used the mounted hook just for demo purposes).

use plugins get raw access to the Vue “vm”, so you can do pretty much anything. But you lose all safety nets and features that the kirby wrapper code offers you.

That’s what I was looking for. Awesome.

Is there more than this?

I don’t think there is :slight_smile:

Hi

I want to extend k-page-create-dialog as well and having it available in all other components.

Applying your suggestions led me to the following solution:

const PAGE_CREATE_DIALOG = {
  extends: 'k-page-create-dialog',
  // place custom code here...
}

panel.plugin('my/plugin', {
  components: {
    'k-page-create-dialog': PAGE_CREATE_DIALOG
  },
  use: [
    function(Vue) {
      const
        VUE_COMPONENTS = Vue.options.components;
      
      Object.keys(VUE_COMPONENTS).forEach(componentName => {
        const COMPONENT = {
          components: {
            'k-page-create-dialog': PAGE_CREATE_DIALOG
          },
          extends: VUE_COMPONENTS[componentName]
        };
        Vue.component(componentName, COMPONENT);
      });
    }
  ]
});

Not sure if this will work out in any case. But so far it works for me.

Thanks for all valuable hints!