K4 Opening k-drawer with button

Before k4 my plugin had a <k-button> and <k-drawer> by using @click on the button i managed to open the drawer. That’s not possible anymore. I checked the lab example where the definition of the fields for the drawer is on the open()

@click="
		$panel.drawer.open({
			component: 'k-form-drawer',
			props: {
				icon: 'box',
				title: 'Form',
				fields: {
					name: {
						label: 'Name',
						type: 'text',
					},
					email: {
						label: 'Email',
						type: 'email',
					},
				},
			},
		})
	"

I would like to avoid re-writing all drawer fields and. How can i just open my old k-drawer definition?

1 Like

Good question – did you find a solution @ponchoelastic?

No I don’t

Too bad, hopefully soon solved

How do your drawer setups look like? What makes it complicated to put the code for your old drawer into the field definition?

Hi @bastianallgeier,
thanks for kicking in. I can only speak for myself but in K3 I used to import a separate single file drawer component by ref which does not seem to work anymore:

this.$refs.myDrawer.open();
this.$refs.myDrawer.close();

…resulting in:

@ponchoelastic pasted code pretty similar to the examples from the lab (which is great by the way). It does work for small chunks pretty well but once components become too complex…well, you might guess: better not inline. Refactoring in this case feels like a backroom somewhat.

Hopefully the issue is just caused by a lack of knowledge :wink:

I had to simplify the example a bit so here we go:

/* index.js */
import myToggle from "./components/fields/myToggle.vue";

window.panel.plugin("namespace/mytoggle", {
  fields: {
    myToggle: myToggle
  }
});
/* myToggle.vue */
<template>
  <div>    
    <k-field class="k-toggle-field">      
      <k-input
        @input="onInput"
        …
      />
    </k-field>    
    <myDrawer
      ref="myDrawer"
      …>
    </myDrawer>    
  </div>
</template>

<script>
import myDrawer from "./MyDrawer.vue"

export default {
  props: {
    value: Boolean,
  },
  components: { myDrawer },
  methods: {
    onInput($event) {
        this.$refs.myDrawer.open();
    }
  }
}
</script>
/* myDrawer.vue  */

<template>
  <k-form-drawer  ref="mydrawer">
    <div> …all the fun… </div>
  </k-form-drawer>
</template>

<script>
export default { 
    methods: {
     close() {
      // formerly working
      this.$refs.mydrawer.close();
      // state error
      /*window.panel.drawer.close(this.$refs.mydrawer)*/
    },		
    open() {		
      // formerly working
      this.$refs.mydrawer.open();
      // state error
      /*window.panel.drawer.open(this.$refs.mydrawer)*/
    }
  }
}
</script>

Sorry, nonsense:

This actually worked:

this.$refs.myDrawer.open(); 
this.$refs.myDrawer.close();

…but this doesn’t:

window.panel.drawer.open(this.$refs.mydrawer);
window.panel.drawer.close(this.$refs.mydrawer)

With the new panel js api, we have more fine-grained control over the drawer state and can solve the issue of nested drawers in a more stable way. That’s the explanation why the old way of using drawer components directly in your template is deprecated.

When you want to create your own, more complex drawer components, this is still very much possible though.

This is an example component plugin for a custom drawer

panel.plugin("my/drawer", {
	components: {
		"k-my-drawer": {
			extends: "k-drawer",
			props: {
				message: String
			},
			template: `
				<k-drawer
					class="k-my-drawer"
					v-bind="$props"
					@cancel="$emit('cancel', $event)"
					@crumb="$emit('crumb', $event)"
					@input="$emit('input', $event)"
					@submit="$emit('submit', $event)"
					@tab="$emit('tab', $event)"
				>
					{{ message }}
				</k-drawer>
			`,
		},
	},
});

And you can open it from a button like this:

$panel.drawer.open({
	component: 'k-my-drawer',
	props: {
		icon: 'box',
		title: 'My drawer',
		message: 'Hello world'
	},
})

Thank you very much @bastianallgeier, that’s quite helpful and I will adapt my component but still: the template component definition feels a bit isolating in terms of coding because the benefits of code separation into single files already became a common pattern. In consequence a rewrite seems inevidable sadly. @ponchoelastic hurry up, mate :wink:

I just wrote it down in the simple version without single file components. You can totally use it like this:

import MyDrawer from "./MyDrawer.vue";

panel.plugin("my/drawer", {
	components: {
		"k-my-drawer": MyDrawer
	},
});

and then MyDrawer.vue would look like this:

<template>
	<k-drawer
		class="k-my-drawer"
		v-bind="$props"
		@cancel="$emit('cancel', $event)"
		@crumb="$emit('crumb', $event)"
		@input="$emit('input', $event)"
		@submit="$emit('submit', $event)"
		@tab="$emit('tab', $event)"
	>
		{{ message }}
	</k-drawer>
</template>

<script>
export default {
	extends: "k-drawer",
	props: {
		message: String
	}
};
</script>

If you already worked with a separate drawer component, there should not be too much work involved to refactor it.

1 Like

That’s it, many thanks!

1 Like