{"id":21615834,"url":"https://github.com/valango/vue-proper","last_synced_at":"2026-05-17T13:06:33.547Z","repository":{"id":40783426,"uuid":"256163949","full_name":"valango/vue-proper","owner":"valango","description":"Keep Vue.js html static props / attributes aside from component code","archived":false,"fork":false,"pushed_at":"2023-01-06T04:07:06.000Z","size":216,"stargazers_count":0,"open_issues_count":12,"forks_count":0,"subscribers_count":3,"default_branch":"dev","last_synced_at":"2024-04-26T03:22:14.423Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/valango.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":"2020-04-16T09:07:02.000Z","updated_at":"2020-04-29T07:46:25.000Z","dependencies_parsed_at":"2023-02-05T07:01:59.052Z","dependency_job_id":null,"html_url":"https://github.com/valango/vue-proper","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valango%2Fvue-proper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valango%2Fvue-proper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valango%2Fvue-proper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valango%2Fvue-proper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/valango","download_url":"https://codeload.github.com/valango/vue-proper/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244257250,"owners_count":20424131,"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":[],"created_at":"2024-11-24T22:12:57.313Z","updated_at":"2026-05-17T13:06:28.527Z","avatar_url":"https://github.com/valango.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vue-proper [![Build Status](https://travis-ci.org/valango/vue-proper.svg?branch=master)](https://travis-ci.org/valango/vue-proper) [![Code coverage](https://codecov.io/gh/valango/vue-proper/branch/master/graph/badge.svg)](https://codecov.io/gh/valango/vue-proper)\n\nKeep [Vue.js](https://vuejs.org/) element attribute definitions aside from\ncomponent code - like _CSS_ keeps aside the _HTML_ styling stuff.\n\n## Problem\n[Vue.js](https://vuejs.org/) and awesome [Quasar framework](https://quasar.dev/)\nprovide super powerful APIs to control component appearance and behavior.\nBut using these features often makes your (HTML at the first place) code complex\nand hard to manage.\n\n_**vue-proper**_ makes it easy to control this complexity, and more.\nTo save your time, try the [vue-proper-demo](https://github.com/valango/vue-proper-demo) first!\n\nThis package also provides lightweight API for managing texts like UI element\nlabels, hints, placeholders etc., also with internationalization.\n\n## Usage\n```\n$ npm i -S vue-proper\n```\n\n### Example\nSomewhere in application boot code:\n```javascript\nimport Vue from 'vue'\n\nVue.mixin(require('vue-proper')(require('./ui-settings')))\n```\nNow, in `my-component.vue`:\n```html\n\u003ctemplate\u003e\n      \u003csome-element v-bind=\"proper('surname')\" v-model=\"surname\" /\u003e\n\u003c/template\u003e\n```\n```javascript\nexport default {\n  methods: {\n    //  Injection point for vue-proper API.\n    proper: () =\u003e undefined    \n  }\n}\n```\nThe `ui-settings.js` file:\n```javascript\nmodule.exports = { \n    // Common defaults\n    rel: 'noopener',\n    target: '_blank',\n    // Components with name containing 'round' will have different styling.\n    ['/round[^!]*!/']: {\n        rounded: true    //  `standout` and `borderless` can be true.\n    },\n    ['/!failed$/']: {    //  Special styling for failed state.\n       color: 'red'\n    }\n}\n```\n\n## How it works\nEvery time an UI element is (re-)rendered, it's `v-bind=` method gets called.\nThis happens quite frequently - on content changes, focus changes, etc...\n\nOn component creation, the do-nothing `proper()` method will be replaced with\na real thing. Then, on every invocation `this.proper('surname')`\nthe following sequence will take place:\n   1. A **_retrieval key_** `':MyComponent\u003esurname!'` is applied on \n   `ui-definitions.js` contents \n     (see [Retrieval algorithm](#retrieval-algorithm)).\n   1. With settings object retrieved, the `ref` property is set to `'surname'` \n   and if `name` property is still not set, it will be `'surname'`, too.\n   1. Settings objects is returned by `proper()` method and will be applied\n   to UI element.\n\n### Retrieval algorithm\n   1. all properties with normal string keys are assigned to result object.\n   1. if property key is `RegExpr` definition and the _retrieval key_ matches,\n   it's contents will be recursively processed from step #1 on and the result\n   be assigned to parent-level result object, overriding conflicting property values.\n\n## API\n### Component instance methods\n**`proper`**`( param= : {string|object} ) : Object  `\nThis instance method will replace your original definition, which should be\njust an empty function - if it is missing, then component can't use `vue-proper`\nservices. Injected instance method can be called with:\n   * **UI element name**:\u003cbr /\u003e\n   _retrieved_ settings, texts, `{ ref: param, name: param }` and `this.$attrs` \n   will be assigned to returned object in this order.\n   * **no arguments**:\u003cbr /\u003e\n   only no-element-specific attributes and contents of `$attrs` are returned.\n   This is useful in child components.\n   * **object instance**\u003cbr /\u003e\n   [inner settings](#mixin-instance-settings) are overridden by matching properties\n   of object instance and clone of original settings object is returned.\n   * **null**\u003cbr /\u003e\n   direct reference to [inner settings](#mixin-instance-settings) is\n   returned, so it may be manipulated directly.\n\n**`properName`**`() : string  `\nIf this property method is defined, then it will be called from\n`this.proper(elementName)` and returned value is used instead of `name`\ninternal setting. Example:\n```javascript\n\n  methods: { \n    proper: () =\u003e undefined, \n    properName () {\n      return this.$router.currentRoute.path\n    }\n  }\n```\n\n### Package exports\n**`mixin`**`(settings= : Object, namespace= : string) : Object  `\nFactory returning mixin definition object.\nNamespace defaults to 'proper' and\nit affects the names of instance methods. Once the settings objects is provided,\nit will be used in following calls.\nThis method is also default export.\n\n**`set`**`(settings : Object) : Object  `\nAssign new settings and return the previous object. Effects already initiated\ncomponents, too. This method is called internally on the first call to `mixin()`.\n`settings` can be nested. All keys that are not acceptable attribute names,\nare treated as _RegExp_ definitions. Opening and closing slashes `'/'` are optional\nand can be used for setting _RegExp_ flags.\n\n**`retrieve`**`(key= : string) : Object  `\nRetrieve the settings. Results are cached internally. Calling this method without\narguments clears the cache.\nThis method is called internally by `proper()` instance method.\n\u003cbr\u003e**NB:** exception is thrown, if dictionary is not initialized.\n\n**`texts`**`(field : string, context : string, mode= : *) : Object  `\nReturns a definition by `\u003ccontext\u003e \".\" \u003cfield\u003e` or `\u003cfield\u003e` just a field itself.\nIf definition found is an object, then it will be returned unchanged. String value\nwill be casted to object `{ label: \u003cstring-value\u003e }`.\nThis method is used internally, too by `proper()` instance method.\u003cbr /\u003e\nWhen called with truish _`mode`_, then empty object is returned, if\nno entry was found in dictionary.\u003cbr /\u003e\nWhen called with _`mode`_ set to _false_, pure text string is returned.\n\n**`texts.get`**`() : Object  `\nReturns an internal dictionary instance. Mutating it's contents will have immediate effect.\n\n**`texts.set`**`( settings : Object ) : Object  `\nSets an internal dictionary object. Returns internal dictionary instance.\nMutating that instance has no effect on original `settings` object.\n\n## Advanced topics\nJust for clarity: whatever properties are returned by `proper()`, only those\nrecognized by particular UI element (native or component) will have effect.\n\n**Never** try to modify any parts of settings dictionary - it's\ncontents should be kept static!\n\n### Mixin instance settings\nThere are several inner settings you may change:\n   * **`compose`**`(el : string, settings : object) : string   ` default \n   implementation returns `\u003cprefix\u003e \":\" \u003cname\u003e \"\u003e\" \u003cel\u003e \"!\" \u003csuffix\u003e`\n   it is not recommended to override this.\n   * **`debug`**`(attributes : object, el : string, retrievalKey : string)   `\n   is called by just before returning the attributes from `proper()`.\n   * **`enhance`**`(attributes : object, el : string)   ` is ha hook enabling to\n   change some attributes from component code.\n   * **`name`**`: string   ` is set to component name on form creation, but can be changed.\n   * **`prefix`**`: string   ` nice place for `vue-router` path or alike.\n   * **`suffix`**`: string   ` nice place for status key.\n   \n### Components wrapping\nIf parent component had some attributes set it did not recognize, these\nwill be available via [Vue.js $attrs](https://vuejs.org/v2/api/#vm-attrs)\ninstance property. Injected `proper()` instance method will check out and\napply those, overriding settings from static dictionary.\n\n### Internationalization\nThere may be several ways to use [vue-i18n](https://github.com/kazupon/vue-i18n)\nor similar packages:\n   * translate the static contents of text dictionary once the language selection is made;\n   * use traditional $t(field) syntax in html template;\n   * call translation API from enhance() hook.\n\nThe first option is probably the best.\n\n### UI element lifecycles\nThis is how Vue.js works - not part of this package, but still good to know. ;)\n\n1. Component initalization\n   * `beforeMount` hook\n   * `v-bind` directives on all elements\n   * `v-model` directives on all elements\n   * `bind` of user-defined directives\n   * `inserted` of user-defined directives\n   * possible auto-focus\n   * `mounted` hook\n1. Component update\n   * `v-bind` directives on all elements\n   * `inserted` of user-defined directives on all elements\n\nSee [Vue.js custom directives](https://vuejs.org/v2/guide/custom-directive.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalango%2Fvue-proper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvalango%2Fvue-proper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalango%2Fvue-proper/lists"}