Skip to content

Instantly share code, notes, and snippets.

@atomjoy
Last active October 20, 2025 08:58
Show Gist options
  • Select an option

  • Save atomjoy/5e72623d62261c8b68f9082343422e51 to your computer and use it in GitHub Desktop.

Select an option

Save atomjoy/5e72623d62261c8b68f9082343422e51 to your computer and use it in GitHub Desktop.
Store with computed and v-model.

Vue Store Computed

Pinia store

File /stores/targets.js

import { ref, computed, nextTick } from 'vue';
import { defineStore, storeToRefs } from 'pinia';
import { useRoute } from 'vue-router';
import router from '@/router';
import axios from 'axios';

export const useItemStore = defineStore('targets', () => {
	// State
	const route = useRoute();	
	let current_page = ref(1);
	let search = ref('');
	let list = ref([]);

	// Getters, Setters, Reactive
	const setPage = computed({
		get: () => {
			return current_page.value;
		},
		set: (v) => {
			current_page.value = v;
			loadList();
		},
	});

	// Actions, Setters
	async function loadList() {
		let dontScroll = 0;    
		
		let res = await axios.get('/api/admin/targets?page=' + current_page.value);    
		list.value = res?.data?.data ?? [];

		// Send params to router to.params.savePosition (scroll behavior)
		if(search.value.length > 0) {
		  dontScroll = 1
		}
    
		router.push({
			query: { page: current_page.value,	},
			params: { savePosition: dontScroll, },
		});
	}
  
	return {
    setPage,
    current_page,
    search,
    list,		
	};
});

Component or input

File PageView.vue

<script setup>
import { useItemStore } from '@/stores/targets.js';
import { onBeforeMount, ref, watch } from 'vue';
import { useRoute } from 'vue-router';

const store = useItemStore();
const route = useRoute();

onBeforeMount(async () => {	
	// Update from browser bar query params here
	store.current_page = route.query.page ?? 1;	
	await store.loadList();
});

watch(
	() => route.query.page,
	async (newId, oldId) => {
		store.current_page = route.query.page ?? 1;
		await store.loadList();
	}
);
</script>

<template>
  <select v-model=store.setPage">...</select> 
  
  <!-- Use defineModel() in component -->
  <Paginate v-model=store.setPage" />
</template>

Router scroll to top

scrollBehavior(to, from, savedPosition) {
	// if the returned position is fals or an empty object, dont scroll.
	if (to.params.savePosition == 1) return {};

	// scroll to anchor
	if (to.hash) {
		let position = { selector: to.hash };
		// if (to.hash === '#scrollto-offset') { position.offset = { y: 100 }}
		return position;
	}

	// Scroll to top (must be 1 if 0 often does not work and add a bigger bottom margin to the form or div where the trigger button is)
	return { top: 1, behavior: 'smooth' };
	
	// Or use and set default scroll behavior to smooth
	// return {x: 0, y: 0}
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment