{"id":23440039,"url":"https://github.com/bassdman/vue-feature-toggle","last_synced_at":"2025-08-08T07:17:29.890Z","repository":{"id":21580098,"uuid":"93316071","full_name":"bassdman/vue-feature-toggle","owner":"bassdman","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-28T05:59:03.000Z","size":124,"stargazers_count":61,"open_issues_count":1,"forks_count":8,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-27T22:15:49.530Z","etag":null,"topics":["feature-flags","feature-toggle","vue","vue-feature-toggle"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bassdman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-04T13:43:41.000Z","updated_at":"2025-06-05T11:02:00.000Z","dependencies_parsed_at":"2025-01-28T06:25:33.708Z","dependency_job_id":"e3771f13-9a8f-435c-85d4-225cfec03d95","html_url":"https://github.com/bassdman/vue-feature-toggle","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/bassdman/vue-feature-toggle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bassdman%2Fvue-feature-toggle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bassdman%2Fvue-feature-toggle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bassdman%2Fvue-feature-toggle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bassdman%2Fvue-feature-toggle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bassdman","download_url":"https://codeload.github.com/bassdman/vue-feature-toggle/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bassdman%2Fvue-feature-toggle/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269381034,"owners_count":24407747,"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","status":"online","status_checked_at":"2025-08-08T02:00:09.200Z","response_time":72,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["feature-flags","feature-toggle","vue","vue-feature-toggle"],"created_at":"2024-12-23T15:39:34.517Z","updated_at":"2025-08-08T07:17:29.868Z","avatar_url":"https://github.com/bassdman.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vue-feature-toggle\n\n\u003e Enables advanced feature-toggle with vue\n\n[![npm version](https://img.shields.io/npm/v/vue-feature-toggle.svg)](https://www.npmjs.com/package/vue-feature-toggle)\n[![npm downloads](https://img.shields.io/npm/dt/vue-feature-toggle.svg)](https://www.npmjs.com/package/vue-feature-toggle)\n[![npm downloads](https://img.shields.io/github/license/mashape/apistatus.svg)](https://www.npmjs.com/package/vue-feature-toggle)\n\n## Info\nVue-Feature-Toggle implements the [feature-toggle-api](https://www.npmjs.com/package/feature-toggle-api) v 4.1.1\".\nOnly a subset of features is listed here. For the others, watch the documentation of the api.\n\n## Install\n\n``` shell\n    npm install vue-feature-toggle --save\n```\n\n## The Problem\nImagine you have an onlineshop with an testmode and in multiple languages. \nYour shop is written in vue. Anywhere you have a vue-template like this:\n``` html\n\u003ccontent-area\u003e\n    \u003c!-- Show important debugging information for testmode --\u003e\n    \u003ctestmode-nav v-if=\"testmode\"\u003e\u003c/testmode-nav\u003e\n\n    \u003c!-- That's the old one, in a few days the new one, commented out here will be released \n        \u003cleft-nav-new\u003e\u003c/left-nav-new\u003e\n    --\u003e\n    \u003cleft-nav\u003e\u003c/left-nav\u003e\n\n    \u003c!-- Every shop has a slider with amazing foodinfo on the startpage--\u003e\n    \u003cstartpage-slider-de ref=\"food/bratwurst\" v-if=\"shop == 'de'\"\u003e\u003c/startpage-slider-de\u003e\n    \u003cstartpage-slider-en ref=\"food/fishnchips\" v-if=\"shop == 'en'\"\u003e\u003c/startpage-slider-en\u003e\n    \u003cstartpage-slider-fr ref=\"food/croissant\" v-if=\"shop == 'fr'\"\u003e\u003c/startpage-slider-fr\u003e\n\n    \u003cfooter-new\u003e\u003c/footer-new\u003e\n    \u003c!-- \n    New footer just went live. When there are some problems, we rollback and comment out the new footer and uncomment the old one\n    \u003cfooter-old\u003e\u003c/footer-old\u003e --\u003e\n\u003c/content-area\u003e\n```\nIt's generally a bad idea to have visibility rules in the template. Of course, by refactoring the template a little bit the code will look better. \nBut that's not the point. The problem is: The view-logic is spread in .html and .js files and if the viewlogic changes, you have to change at least them. And all visibility rules are spread over the whole system.\nThat's not good.\n\n## The solution\nFeature-toggle. All View-Logic is placed in one place. This can be a config file, a webservice or a tool with a User Interface.a\nWhen you want to change a visibility rule, for example \"Show feature XYZ also in the french shop\", you just have to update the config or add this info in an UI. And no developer is needed for it.\n\n\u003ca href=\"https://martinfowler.com/articles/feature-toggles.html\"\u003eRead the article from Martin Fowler about feature toggle for a more understanding.\u003c/a\u003e\n\n## The Usage\nLook in the example folder for working examples.\n\n### Initialisation\nCreate a vue project, if you don't have one. \n\nNow install the vue-feature-toggle component. \n``` shell\n    npm install vue-feature-toggle --save\n```\n\n\nNow go into any vue-component and add the following:\n``` html\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n        \u003ch1\u003eWe test vue-feature-toggle in vue3\u003c/h1\u003e\n    \u003c!-- The name property is required --\u003e\n        \u003cfeature name=\"feature1\"\u003eThis is \"Feature1\"\u003c/feature\u003e\n        \n        \u003cfeature name=\"feature2\"\u003eThis is \"Feature2\"\u003c/feature\u003e\n\n        \u003c!-- The variant property is optional and can be any string --\u003e\n        \u003cfeature name=\"feature2\" variant=\"new\"\u003eThis is \"Feature2\" with variant \"new\"\u003c/feature\u003e\n        \u003cfeature name=\"feature2\" variant=\"old\"\u003eThis \"Feature2\" with variant \"old\"\u003c/feature\u003e\n        \u003cfeature name=\"feature2\" variant=\"grumpfel\"\u003eThis \"Feature2\" with variant \"grumpfel\"\u003c/feature\u003e\n        \n        \u003cfeature name=\"feature3\" variant=\"old\" data=\"grumpfel\"\u003eThis \"Feature3\" with variant \"old\" has some Data.\u003c/feature\u003e\n        \u003cfeature name=\"feature3\" variant=\"new\" :data=\"{'text':'grumpfel'}\"\u003eThis \"Feature3\" with variant \"old\" has some Data. (watch the : before the data-attribute. Otherwise you'll get this as a string...)\u003c/feature\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript setup lang=\"ts\"\u003e\nimport feature from 'vue-feature-toggle';\n\n//All Feature2-Features will always be shown\nfeature.setFlag('feature2',true);\n\n//hide feature2-Features with variant \"new\"\nfeature.setFlag('feature2','new',false);\n//Feature.showLogs();\n\u003c/script\u003e\n```\n\nSee more the projects in the [example-folder](https://github.com/bassdman/vue-feature-toggle/tree/master/examples).\n\n### Features\n[Only a subset of features is listed here. See the documentation of the feature-toggle-api for more features](https://www.npmjs.com/package/feature-toggle-api)\n\nFor the next examples we will always use the HTML from above. Just insert the visibility rules under the other rule\n\n#### Basic visibility\n```javascript\n// shows Feature1\n//Feature2 is not configured, so it will be hidden\nfeature.setFlag('feature1',true);\n\n//You can also write it like this\nfeature.setFlag('feature1',function (rule) {\n        //here would be some more complex logic, in this example we keep it simple\n        return true;\n});\n```\n```javascript\n/* \n    shows all features with name feature2, in this case: \n    \u003cfeature name=\"feature2\"/\u003e\n    \u003cfeature name=\"feature2\" variant=\"new\"/\u003e\n    \u003cfeature name=\"feature2\" variant=\"old\"/\u003e\n    \u003cfeature name=\"feature2\" variant=\"grumpfel\"/\u003e\n */\nfeature.setFlag('feature2', function (rule) {\n        return true;\n});\n\n/*\n    This overwrites the rule above for \"feature2\", variant \"new\"    \n    \u003cfeature name=\"feature2\"/\u003e -\u003e shown\n    \u003cfeature name=\"feature2\" variant=\"new\"/\u003e -\u003e hidden\n    \u003cfeature name=\"feature2\" variant=\"old\"/\u003e -\u003e shown\n    \u003cfeature name=\"feature2\" variant=\"grumpfel\"/\u003e -\u003e shown\n*/\nfeature.setFlag('feature2','new', function (rule) {\n        return false;\n});\n```\n```javascript\n/*\nYou can pass data via the data-attribute. Corresp. HTML-Tag: \u003cfeature name=\"feature3\" :data=\"grumpfel\"/\u003e\n*/\nfeature.setFlag('feature3','new', function (rule) {\n      return rule.data == \"grumpfel\";\n});\n\n//Write a : before the data-tag to parse the content in the data-attribute \u003cfeature name=\"feature3\" :data=\"{'text':'grumpfel'\"/\u003e Otherwise the data is returned as a string.\nfeature.setFlag('feature3','new', function (rule) {\n      return rule.data.text == \"grumpfel\";\n});\n```\n#### Default flag\nBored of writing the same flag rule again and again? Use defaultflag. This is the default-rule and will be overwritten by feature.setFlag() - rules.\n``` javascript\nfeature.setDefaultFlag(function(rule){\n    return true;\n});\n\nfeature.setFlag('feature2', 'new', function(rule){\n    return false;\n});\n/*\n    \"Feature2\", variant \"new\" is overwritten, all other features have the defaultVisibility\n    \u003cfeature name=\"feature2\"/\u003e -\u003e shown\n    \u003cfeature name=\"feature2\" variant=\"new\"/\u003e -\u003e hidden\n    \u003cfeature name=\"feature2\" variant=\"old\"/\u003e -\u003e shown\n    \u003cfeature name=\"feature2\" variant=\"grumpfel\"/\u003e -\u003e shown\n*/\n```\n\n#### Required Flag\nThis rule is allways executed, before the other rules. When it returns false, the other rules are ignored.\n``` javascript\n/*\n   Imagine a config that is loaded via ajax. When the name is in the config, it returns true.\n   And this config looks like this: \n   var globalConfig = { \"feature2\" : true }\n*/\n\nfeature.setRequiredFlag(function(rule){\n    //In this case it returns true, when name == 'feature2'\n    return globalConfig[rule.name] === true;\n});\n\n/*\n  feature2, variant \"new\" returns false, but requiredConfig returns true. Both rules must match, so it will be hidden\n*/\nfeature.setFlag('feature2','new',function(rule){\n    return false;\n});\n\n/*\n  feature3 returns true, but requiredConfig returns false. Both rules must match, so Feature3 is hidden\n*/\nfeature.setFlag('feature3',function(rule){\n    return true;\n});\n\n/*\n    \u003cfeature name=\"feature2\"/\u003e -\u003e shown\n    \u003cfeature name=\"feature2\" variant=\"new\"/\u003e -\u003e hidden\n    \u003cfeature name=\"feature2\" variant=\"old\"/\u003e -\u003e shown\n    \u003cfeature name=\"feature2\" variant=\"grumpfel\"/\u003e -\u003e shown\n    \n     \u003cfeature name=\"feature3\" variant=\"old\"/\u003e -\u003e hidden\n    \u003cfeature name=\"feature3\" variant=\"new\"/\u003e -\u003e hidden\n*/\n```\n\n#### Container Tag\nNormally a feature has a div-element as root-element.\n```html\n    \u003cfeature name=\"anAmazingFeature\"\u003ean amazing feature\u003c/feature\u003e\n    will be rendered to (if visible):\n    \u003cdiv\u003ean amazing feature\u003c/div\u003e\n```\nBut unfortunately sometimes div-elements are already styled by legacy-css-classes.\nTo prevent this, you can define the root-element.\n```html\n    \u003cfeature name=\"anAmazingFeature\" tag=\"span\"\u003ean amazing feature\u003c/feature\u003e\n    will be rendered to (if visible):\n    \u003cspan\u003ean amazing feature\u003c/span\u003e\n```\n\n#### ShowLogs\nImagine this following html-snippet:\n```html\n    \u003c!-- Why is this ******* feature hidden? I checked the visibilityrule. It should be visible... --\u003e\n    \u003cfeature name=\"anAmazingFeature\"\u003eThis feature should be shown\u003c/feature\u003e\n```\nAll developers of the world agree with you, debugging sth lik this is horrible. But don't worry, we have a perfect solution for it. And it's just one line of code.\n```javascript\nfeature.showLogs(); //or feature.showLogs(true);\n```\nThis returns a log like the following:\n```html\nCheck Visibility of Feature \"anAmazingFeature\".\nThe requiredVisibility rule returns false. This feature will be hidden.\n\nCheck Visibility of Feature \"anotherAmazingFeature\", variant \"new\" with data {\"id\":\"bla\"}.\nThe requiredVisibility rule returns true. This feature will be shown when no other rule rejects it.\nNo visibility rule found matching name and variant.\nNo rules found for name anotherAmazingFeature without variants.\nNo default rule found.\nOnly the requiredVisibility rule was found. This returned true. =\u003e This feature will be visible.\n```\nWith this you don't have to waste your time with debugging the visibility state. \n\n#### Log\nLog a custom message, when showLogs() == true.\n```javascript\nfeature.log(\"Here's my custom message\");\n```\n\n#### Noscript\nYou work in a company and your customers have disabled javascript? Well, that makes life harder but we can still use it. We can provide at least a basic functionality with pure css.\nJust look at the modified index.html file.\n``` html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\n\u003chead\u003e\n  \u003cmeta charset=\"utf-8\"\u003e\n  \u003ctitle\u003evue-feature-example\u003c/title\u003e\n   \u003cstyle type=\"text/css\"\u003e\n   /*Hides all features by default. When javascript is enabled, this attribute is overwritten*/\n    feature{\n      display:none;\n    }\n\n    /*Shows all features with noscript attribute*/\n    feature[noscript=\"noscript\"], feature[noscript=\"true\"]{\n      display:block;\n    }\n    \u003c/style\u003e\n\u003c/head\u003e\n\n\u003cbody\u003e\n  \u003cdiv id=\"app\"\u003e\n        \u003cfeature name=\"feature1\"\u003eThis is hidden without javascript\u003c/feature\u003e\n        \n        \u003cfeature name=\"feature2\" noscript=\"noscript\"\u003eThis is shown without javascript.\u003c/feature\u003e\n        \u003cfeature name=\"feature2\" variant=\"new\" noscript=\"true\"\u003eThis is shown without javascript.\u003c/feature\u003e\n  \u003c/div\u003e\n  \u003cscript src=\"dist/build.js\"\u003e\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n## License\t\n\u003ca href=\"https://opensource.org/licenses/MIT\"\u003eMIT\u003c/a\u003e.\nCopyright (c) 2025 Manuel Gelsen\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbassdman%2Fvue-feature-toggle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbassdman%2Fvue-feature-toggle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbassdman%2Fvue-feature-toggle/lists"}