I am using PrimeVue Splitter with Vue3 and composition API. I want to make the size of each panel dynamic , so when I click a button they return to their original size.
This is what I have so far
<button @click="fixPanels()" >fix</button>
<Splitter style="height: 100%" class="mb-3">
<SplitterPanel :size=smallPanelSize >
Panel 1
</SplitterPanel>
<SplitterPanel :size=bigPanelSize >
Panel 2
</SplitterPanel>
</Splitter>
export default {
setup(){
let smallPanelSize = ref(30)
let bigPanelSize = ref(70)
const fixPanels = ()=>{
message.value = 30;
bigPanelSize.value = 70
}
return{smallPanelSize, bigPanelSize, fixPanels}
}
}
I can resize the panels freely, but when fixPanels
is clicked, they dont return to their original size. I guess I have to use two-way binding somehow or v-model
but I dont know how, there is no input here. If this is impossible, can you suggest a similar resizable panels component that the panel size is dynamically controlled?
Thank you
It seems that the SplitterPanel
component does not handle reactive sizes. As a result, the prefix sizes are determined when the component is loaded and cannot be reset via reactivity.
Therefore, the solution is to reload the components to force the sizes to be reset.
For this, I created a Panels
component which will be used only to display the panels and its reset button. The sizes will be retrieved via props
and not assigned within the component. The resize button will send an event via emit
in order to signal to the parent component the will to reload the component, in order to reset the sizes.
The parent component will create the two default size variables with ref
and send them to the props. The event will also be retrieved to call the fixPanels
function. The only subtlety is to manage to force the reload of the Panels
component. For this, I added a key
value to the Panels
component which will be incremented each time the fixPanels
function is called. The purpose of this variable is only to make the child think that the values of the component have changed and to create the need to reload it.
Just below, the two coded components that correspond to my explanations. (I used Vue 3 with the composition API and TypeScript, but you will probably know how to convert it to Vue 3 Option, if needed)
Panels.vue
<template>
<button @click="$emit('reload')">fix</button>
<Splitter style="height: 100%" class="mb-3">
<SplitterPanel :size="smallPanelSize">
Panel 1
</SplitterPanel>
<SplitterPanel :size="bigPanelSize">
Panel 2
</SplitterPanel>
</Splitter>
</template>
<script setup lang="ts">
import Splitter from "primevue/splitter";
import SplitterPanel from "primevue/splitterpanel";
const props = defineProps<{smallPanelSize: number, bigPanelSize:number}>();
</script>
ManagePanel.vue
<script setup lang="ts">
import { ref } from "vue";
import Panels from "./components/Panels.vue";
let small = ref(30);
let big = ref(70);
let componentKey = ref(0);
function forceRender() {
componentKey.value += 1;
}
function fixPanels() {
small.value = 30;
big.value = 70;
forceRender();
}
</script>
<template>
<Panels
:smallPanelSize="small"
:bigPanelSize="big"
:key="componentKey"
@reload="fixPanels"
/>
</template>