{"id":13419905,"url":"https://github.com/oarepo/vue-query-synchronizer","last_synced_at":"2025-03-15T06:30:43.493Z","repository":{"id":36152940,"uuid":"221757455","full_name":"oarepo/vue-query-synchronizer","owner":"oarepo","description":"browser addressbar model/query synchronization for vuejs + router","archived":true,"fork":false,"pushed_at":"2022-12-04T20:28:00.000Z","size":2416,"stargazers_count":37,"open_issues_count":6,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-09-15T05:09:36.840Z","etag":null,"topics":["query","synchronization","vue-router","vuejs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oarepo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-14T18:01:11.000Z","updated_at":"2024-04-28T21:02:00.000Z","dependencies_parsed_at":"2023-01-16T23:45:17.727Z","dependency_job_id":null,"html_url":"https://github.com/oarepo/vue-query-synchronizer","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oarepo%2Fvue-query-synchronizer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oarepo%2Fvue-query-synchronizer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oarepo%2Fvue-query-synchronizer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oarepo%2Fvue-query-synchronizer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oarepo","download_url":"https://codeload.github.com/oarepo/vue-query-synchronizer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221548134,"owners_count":16840975,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["query","synchronization","vue-router","vuejs"],"created_at":"2024-07-30T22:01:22.611Z","updated_at":"2024-10-26T15:30:54.818Z","avatar_url":"https://github.com/oarepo.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# @oarepo/vue-query-synchronizer\n\nThis is Vue 3 implementation, for vue2 look at the [vue-2](https://github.com/oarepo/vue-query-synchronizer/tree/vue-2) branch\n\nIn browser applications, address bar should be the most important source\nof truth. When user performs data filtering, sorting, pagination, the url should\nchange so that the result of the filtering is bookmarkable/shareable.\n\nTraditionally vue component would listen on query change and copy the\nquery params to an internal model. This would be then used by an input\ncomponent. Whenever the input is changed, an event listener (after optional\ndebouncing) would propagate the change back to the query.\n\nThis library does all of this on the background, leaving you with just\na couple of lines of code.\n\n\u003c!-- toc --\u003e\n\n- [Installation](#installation)\n  * [From sources](#from-sources)\n- [Usage](#usage)\n  * [Plugin installation](#plugin-installation)\n  * [Router configuration](#router-configuration)\n  * [Component](#component)\n- [Demo setup and run](#demo-setup-and-run)\n  * [Screenshot](#screenshot)\n- [Library build](#library-build)\n- [API](#api)\n  * [``QuerySynchronizer`` plugin configuration](#querysynchronizer-plugin-configuration)\n  * [``query``](#query)\n    + [definition](#definition)\n  * [``Datatype``](#datatype)\n  * [Callbacks and signals](#callbacks-and-signals)\n    + [``onInit``](#oninit)\n    + [``onLoad``](#onload)\n    + [``onChange``](#onchange)\n\n\u003c!-- tocstop --\u003e\n\n## Installation\n```\nyarn add @oarepo/vue-query-synchronizer@^3.0.0\n```\n\n### From sources\n```\nyarn build\ncd dist; yarn link\n\ncd your_project\nyarn link @oarepo/vue-query-synchronizer\n```\n\n## Usage\n\n### Plugin installation\n\nAdd the following to ``main.js`` (in quasar ``boot/....js``)\n\n```javascript\nimport QuerySynchronizer from '@oarepo/vue-query-synchronizer'\n\nVue.use(QuerySynchronizer, {\n    router: router\n})\n```\nSee [src/main.ts](src/main.ts) for the whole file.\n\n### Router configuration\n\nIn router configuration, mark which query parameters with a given type and default value\nshould be synchronized with the component state:\n\n```javascript\nimport { query } from '@oarepo/vue-query-synchronizer'\n\nconst routes = [\n{\n    path: '/',\n    name: 'home',\n    meta: {\n        query: {\n           'page': 'int:1'\n        }\n    },\n    component: Home\n}\n]\n```\nFull example at [src/router.ts](src/router.ts)\n\n### Component\n\n#### Composition-api based\n\nCall ``useQuery()`` and use the result as usual (for example as model for input):\n\n```vue\n\u003ctemplate\u003e\n\u003cdiv\u003e\n    \u003cinput v-model=\"query.filter\"\u003e\u003cbr\u003e\u003cbr\u003e\n\u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport { useQuery } from '@oarepo/vue-query-synchronizer'\n\nexport default {\n    setup() {\n      return {\n        query: useQuery(),\n      }\n    }\n}\n\u003c/script\u003e\n```\n\nFull example at [src/CompositionHome.vue](src/CompositionHome.vue)\n\n#### Options-based component\n\nIn component, use ``this.$query`` to access parsed query. Then\nyou can use properties at ``$query``, for example \n``$query.filter``, ``$query.sort`` as normal models for\nhtml inputs or as models for any other components:\n\n```vue\n\u003ctemplate\u003e\n\u003cdiv\u003e\n    \u003cinput v-model=\"$query.filter\"\u003e\u003cbr\u003e\u003cbr\u003e\n\u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nexport default {\n    name: 'home',\n}\n\u003c/script\u003e\n```\nFull example at [src/Home.vue](src/Home.vue)\n\n## Demo setup and run\n```\nyarn install\nyarn run serve\n```\n\n### Screenshot\n\n![screenshot](public/screenshot.png)\n\n## Library build\n```\nyarn run build\n```\n\n## API\n\n### ``QuerySynchronizer`` plugin configuration\n\nDuring plugin registration, ``router`` must be passed in.\n \n\n```javascript\nimport QuerySynchronizer from '@oarepo/vue-query-synchronizer'\n\nVue.use(QuerySynchronizer, {\n    router: router,\n    datatypes: {\n        name: handler\n    },\n    debug: false,\n    navigationOperation: 'push' | 'replace' | \n            ((query, router) =\u003e 'push' | 'replace')\n})\n```\n\nSetting ``debug`` to ``true`` will log the parsed and serialized query parameters.\n\nNavigation operation can be used to override the default operation \ncalled on the router (push). Either method name (push, replace) might be\nbe passed or a callable, that can decide which operation to perform.\n\n### Route ``meta`` definition\n\nThe potential query parameters with data types are stored in route's\n``meta.query`` property in the form of ``param_name``:``definition``.\n\n#### definition\n\nDefinition can be:\n\n   * default string value (``test``)\n   \n   * datatype followed by a default value\n     (``int:1``)\n     \n   * an object:\n\n```javascript\n{\n    datatype: 'string',\n    defaultValue: null\n}\n``` \n\nThe object can define a datatype, which is implicitly string. The datatype\ndefines how the value from URL is converted to model and vice versa. Datatypes\nare pluggable, see ``Datatype`` section later in the readme for details. \n\nIf ``defaultValue`` is set and a value is not present in the URL, the model\nis set to this value. URL is not changed. When a default value is \nprogrammatically set on the parameter (for example, user enters it in input),\nthe parameter is removed from the url.  \n\n**Note:** This means that if you change the default value of a parameter\nduring the lifetime of your application, user's bookmarks will start\nbehaving differently as your code will receive the new default values,\nnot the ones used when user bookmarked the page.\n\n### ``Datatype``\n\nA datatype provides means to convert url parameter into an internal model\nvalue and vice versa. The pre-installed datatypes are:\n   * string - a no-op converter\n   * number - converts string value of the number in url into a javascript number\n   * bool - if the parameter is present (with whatever value), returns true else false\n   * array - returns an array of string (for parameters with multiple values)\n   \nA custom datatype can be implemented as follows:\n\n```javascript\n\nVue.use(QuerySynchronizer, {\n    router: router,\n    datatypes: {\n        lowecase: {\n            parseDefault(value) {\n                // parses the default value from the strings above\n                return (value || '').toLowerCase()\n            },\n            parse(value, defaultValue) {\n                // value is: undefined if property is not present in the url\n                // null if property is in url but without a value\n                // string value if property is written as url?key=value\n \n                // note: defaultValue has been parsed previously so that\n                // it already is in the javascript format\n                return value ? value.toLowerCase() : defaultValue \n            },\n            serialize (value, defaultValue) {\n                // this method must return undefined, null or string instance\n                // returning undefined will remove the property from query\n                if (value === defaultValue) { return undefined }\n                // returning null will put url?key without a value to the url\n                if (value === '') { return null }\n                // will put url?key=value into the url\n                return value.toLowerCase()\n            }\n        }\n    }\n})\n\n```\n\nDefault datatypes are implemented by importable ``StringDatatype``, \n``IntDatatype``, ``BoolDatatype``, ``ArrayDatatype``.\n\nYou can use them to create composite datatypes, for example an array\nof numbers.\n\n```javascript\nArrayOfNumbersDatatype = {\n    parseDefault(value) {\n        return ArrayDatatype.parseDefault(value).map(\n            x =\u003e IntDatatype.parse(x, null)\n        )\n    },\n    parse(value, defaultValue) {\n        return ArrayDatatype.parse(value, defaultValue).\n            map(x=\u003eIntDatatype.parse(x, null))\n    },\n    serialize (value, defaultValue) {\n        return ArrayDatatype.serialize(\n            value.map(x =\u003e NumberDataType.serialize(value, null)),\n            defaultValue)\n    }\n}\n```\n\n### Callbacks and signals\n\nThe following signals can be specified at the query level:\n\n```javascript\nimport { query } from '@oarepo/vue-query-synchronizer'\n\nconst routes = [\n{\n    path: '/',\n    name: 'home',\n    meta: {\n        query: {...},\n        querySettings: {\n            onInit (paramsList) { paramsList },\n            onLoad (query) { /* do something with query */ },\n            onChange (newQuery, query) { /* do something with newQuery */ }\n        }\n    },\n    component: Home\n}\n]\n```\n\n#### ``onInit``\n\nonInit is called when the query is loaded. This signal can be used for example to set default values\nstored in local storage or on the server.\n\n#### ``onLoad``\n\ncalled after browser query parameters are parsed and before they are returned to the component.\n\n#### ``onChange``\n\ncalled after just before the url is changed. Can be used to store the values to local storage\nso that the next onInit picks them and uses them as default. The callback takes two parameters:\n  * ``newQuery`` is the new query that will be set to URL. Does not contain props with default values\n  * ``query`` contains the whole current query object with resolved default values\n\n## API docs\n\nSee [docs](https://oarepo.github.io/vue-query-synchronizer/) \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foarepo%2Fvue-query-synchronizer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foarepo%2Fvue-query-synchronizer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foarepo%2Fvue-query-synchronizer/lists"}