{"id":13808929,"url":"https://github.com/willmendesneto/ngx-feature-toggle","last_synced_at":"2025-05-16T15:07:45.168Z","repository":{"id":21264310,"uuid":"92042010","full_name":"willmendesneto/ngx-feature-toggle","owner":"willmendesneto","description":"Your module to handle with feature toggles in Angular applications easier.","archived":false,"fork":false,"pushed_at":"2025-04-16T15:30:03.000Z","size":3738,"stargazers_count":99,"open_issues_count":5,"forks_count":12,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-12T12:13:50.537Z","etag":null,"topics":["angular","feature-flags","feature-toggle","flags","hacktoberfest","ngx-feature-toggle"],"latest_commit_sha":null,"homepage":"","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/willmendesneto.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-05-22T10:36:33.000Z","updated_at":"2025-04-02T12:45:52.000Z","dependencies_parsed_at":"2024-01-31T07:29:00.627Z","dependency_job_id":"bf90d9c2-6667-4438-ba96-3153babb1741","html_url":"https://github.com/willmendesneto/ngx-feature-toggle","commit_stats":{"total_commits":305,"total_committers":6,"mean_commits":"50.833333333333336","dds":"0.43934426229508194","last_synced_commit":"a2572ba8887c2d3b993572ed8bbf5fde04fe525c"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willmendesneto%2Fngx-feature-toggle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willmendesneto%2Fngx-feature-toggle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willmendesneto%2Fngx-feature-toggle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willmendesneto%2Fngx-feature-toggle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/willmendesneto","download_url":"https://codeload.github.com/willmendesneto/ngx-feature-toggle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254256254,"owners_count":22040258,"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":["angular","feature-flags","feature-toggle","flags","hacktoberfest","ngx-feature-toggle"],"created_at":"2024-08-04T01:01:55.366Z","updated_at":"2025-05-16T15:07:45.105Z","avatar_url":"https://github.com/willmendesneto.png","language":"TypeScript","funding_links":[],"categories":["Architecture and Advanced Topics"],"sub_categories":["Feature Flags"],"readme":"# NGX Feature Toggle\n\n[![Dependency Status](https://david-dm.org/willmendesneto/ngx-feature-toggle.svg)](https://david-dm.org/willmendesneto/ngx-feature-toggle)\n[![npm](https://img.shields.io/badge/stackblitz-online-orange.svg)](https://stackblitz.com/edit/ngx-feature-toggle-sample)\n\n[![NPM](https://nodei.co/npm/ngx-feature-toggle.png?downloads=true\u0026downloadRank=true\u0026stars=true)](https://npmjs.org/ngx-feature-toggle)\n[![NPM](https://nodei.co/npm-dl/ngx-feature-toggle.png?height=3\u0026months=3)](https://npmjs.org/ngx-feature-toggle)\n\n[![Build Status](https://circleci.com/gh/willmendesneto/ngx-feature-toggle.svg?style=shield)](https://circleci.com/gh/willmendesneto/ngx-feature-toggle)\n[![Coverage Status](https://coveralls.io/repos/willmendesneto/ngx-feature-toggle/badge.svg?branch=master)](https://coveralls.io/r/willmendesneto/ngx-feature-toggle?branch=master)\n[![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/ngx-feature-toggle.svg)](https://bundlephobia.com/result?p=ngx-feature-toggle)\n[![npm](https://img.shields.io/npm/l/express.svg?maxAge=2592000)](/LICENSE)\n\nYour module to handle with [feature toggles](http://martinfowler.com/bliki/FeatureToggle.html) in Angular applications easier.\n\n## Why Feature toggle?\n\n\u003e This is a common concept, but why use this directive instead solve it via server-side rendering?\n\nThe idea of this directive is make this process transparent and easier. So the main point is integrate this directive with other tooling process, such as:\n\n- Server-side rendering;\n- Progressive rendering;\n- Any other that you like :)\n\nYou can integrate with WebSockets or handling this in a EventSourcing architecture. It's totally transparent for you and you can integrate easier in your application.\n\n- [Demo](#demo)\n- [Install](#install)\n- [Setup](#setup)\n- [Development](#development)\n- [Contribute](#contribute)\n\n## Demo\n\nTry out the demos on Stackblitz:\n\n- [Components and directives example](https://stackblitz.com/edit/ngx-feature-toggle-sample)\n- [Routing Guards example](https://stackblitz.com/edit/ngx-feature-toggle-routing-guard-sample)\n\n## Install\n\nYou can get it on NPM installing `ngx-feature-toggle` module as a project dependency.\n\n```shell\nnpm install ngx-feature-toggle --save\n```\n\n## Setup\n\nYou'll need to add `FeatureToggleModule` to your application module. So that, the `featureToggle` components will be accessible in your application.\n\n```typescript\n...\nimport { FeatureToggleModule } from 'ngx-feature-toggle';\n...\n@NgModule({\n  declarations: [\n    YourAppComponent\n  ],\n  imports: [\n    ...\n    FeatureToggleModule,\n    ...\n  ],\n  providers: [],\n  bootstrap: [YourAppComponent]\n})\n\nexport class YourAppComponent {}\n\n```\n\nNow you just need to add a configuration in your application root component. Your feature toggle configuration can be added using different approaches, such as:\n\n- RXJS subscribe information;\n- HTTP Request;\n- CQRS event data;\n- File information;\n- etc;\n\nAfter that, you can use the `featureToggle` components and directives in your templates, passing the string based on the feature toggle configuration data.\n\n## Module\n\n### Components and Directives\n\n- `feature-toggle-provider`: Handle with feature toggle configuration in your application. It adds the default values of your enabled/disabled features;\n- `*featureToggle`: Directive that handles with feature toggle check. So that, the component will be rendered/removed based on the feature toggle configuration is enabled;\n- `*featureToggleWhenDisabled`: Directive that handles with feature toggle check. So that, the component will be rendered/removed when the feature toggle configuration is disabled;\n\n```typescript\nimport { Component } from '@angular/core';\n\n@Component({\n  selector: 'component-docs',\n  template: `\n    \u003cfeature-toggle-provider [features]=\"featureToggleData\"\u003e\n      \u003cdiv *featureToggle=\"'enableSecondText'\"\u003e\n        \u003cp\u003econdition is true and \"featureToggle\" is enabled.\u003c/p\u003e\n      \u003c/div\u003e\n      \u003cdiv *featureToggle=\"'enableFirstText'\"\u003e\n        \u003cp\u003econdition is false and \"featureToggle\" is disabled. In that case this content should not be rendered.\u003c/p\u003e\n      \u003c/div\u003e\n      \u003cdiv *featureToggle=\"'!enableFirstText'\"\u003e\n        \u003cp\u003e\n          condition is false and \"featureToggle\" is disabled\n          \u003cb\u003ebut it has \"!\" as a prefix of the feature toggle to be checked.\u003c/b\u003e\n          In that case this content should be rendered.\n        \u003c/p\u003e\n      \u003c/div\u003e\n      \u003cdiv\n        class=\"combined-feature-toggles-with-truthly-option\"\n        *featureToggle=\"['!enableFirstText', 'enableSecondText']\"\n      \u003e\n        \u003cp\u003e\n          This is a combined condition. It shows if \u003cb\u003eenableSecondText\u003c/b\u003e is true and \u003cb\u003eenableFirstText\u003c/b\u003e is falsy,\n          but it has \"!\" as a prefix. If both cases are correct, then the \"featureToggle\" is enabled and rendering this\n          component.\n        \u003c/p\u003e\n      \u003c/div\u003e\n    \u003c/feature-toggle-provider\u003e\n  `,\n})\nexport class ComponentDocsComponent {\n  public featureToggleData: any = {\n    enableFirstText: false,\n    enableSecondText: true,\n  };\n}\n```\n\n### Route Guards\n\nIn some scenarios when you need to prevent the route to be loaded, you can use `NgxFeatureToggleCanLoadGuard`, by passing the class and configuration of the feature toggle to be checked in your route data.\n\n```js\n...\nexport const routes: Routes = [\n\n  {\n    path: 'home',\n    component: HomeComponent,\n    canActivate: [NgxFeatureToggleCanLoadGuard],\n    data: {\n      // Using array as configuration\n      featureToggle: [\n        // This configuration will check if feature toggle is enabled\n        'enableSecondText',\n        // This configuration will check if feature toggle is disabled\n        // since it has `!` prefix in the configuration\n        '!enableFirstText'\n      ],\n    },\n  },\n  {\n    path: 'dashboard',\n    component: DashboardComponent,\n    canActivate: [NgxFeatureToggleCanLoadGuard],\n    data: {\n      // Using string as configuration\n      featureToggle: 'enableSecondText',\n    },\n  },\n];\n...\n```\n\nAlso, you can use `NgxFeatureToggleRouteGuard` to check if the route should be activated or not by passing the class and configuration of the feature toggle to be checked in your route data.\n\n```js\n...\nexport const routes: Routes = [\n\n  {\n    path: 'home',\n    component: HomeComponent,\n    canActivate: [NgxFeatureToggleRouteGuard],\n    data: {\n      // Using array as configuration\n      featureToggle: [\n        // This configuration will check if feature toggle is enabled\n        'enableSecondText',\n        // This configuration will check if feature toggle is disabled\n        // since it has `!` prefix in the configuration\n        '!enableFirstText'\n      ],\n    },\n  },\n  {\n    path: 'dashboard',\n    component: DashboardComponent,\n    canActivate: [NgxFeatureToggleRouteGuard],\n    data: {\n      // Using string as configuration\n      featureToggle: 'enableSecondText',\n    },\n  },\n];\n...\n```\n\nIn both route guards you can pass route data with feature toggle as an array. For scenarios when you need to check for feature toggles enabled and/or disabled you can easily configure it by passing `!` if the application should check if the feature toggle is disabled\n\n```js\n...\nexport const routes: Routes = [\n  {\n    path: 'home',\n    component: HomeComponent,\n    canActivate: [NgxFeatureToggleRouteGuard],\n    data: {\n      // Using array as configuration\n      featureToggle: [\n        // This configuration will check if feature toggle is enabled\n        'enableSecondText',\n        // This configuration will check if feature toggle is disabled\n        // since it has `!` prefix in the configuration\n        '!enableFirstText'\n      ],\n    },\n  },\n  {\n    path: 'dashboard',\n    component: DashboardComponent,\n    canActivate: [NgxFeatureToggleRouteGuard],\n    data: {\n      // Using string as configuration\n      featureToggle: 'enableSecondText',\n    },\n  },\n];\n...\n```\n\nIn this case, we are combining the checks. So the component will be activated if `enableSecondText` is configured as `true` AND `enableFirstText` is configured as `false`. With that configuration you can have all the flexibility to cover different scenarios in your app.\n\nUse `NgxFeatureToggleRouteGuard` to control when the child component of a specific component can be activate via routing. It can be passed as an array of items.\n\n```js\n...\nexport const routes: Routes = [\n  {\n    path: 'customer',\n    component: CustomerComponent,\n    canActivateChild: [NgxFeatureToggleRouteGuard],\n    children: [\n      {\n        path: ':id',\n        component: CustomerDetailComponent,\n        // This is the featureToggle configuration for\n        // the child component. It can also use\n        // a combination of feature toggles\n        data: {\n          featureToggle: [\n            // This configuration will check if feature toggle is enabled\n            'enableCustomerPage',\n            // This configuration will check if feature toggle is disabled\n            // since it has `!` prefix in the configuration\n            '!enableChildrenNavigation'],\n        },\n      },\n    ],\n  },\n  {\n    path: 'dashboard',\n    component: DashboardComponent,\n    canActivateChild: [NgxFeatureToggleRouteGuard],\n    children: [\n      {\n        path: ':id',\n        component: DashboardDetailsComponent,\n        // This is the featureToggle configuration for\n        // the child component. It can also use\n        // a combination of feature toggles\n        data: {\n          // using string to configure\n          featureToggle: 'enableDashboardDetailsPage',\n        },\n      },\n    ],\n  },\n];\n...\n```\n\n#### Redirects\n\nYou might have some specific requirements that you should redirect a user to a specific route in case of a feature flag is disabled. For that, you can use `redirectTo` as a mechanism to redirect a user in a specific route when it tries to access in a route with a CanActivate/CanActivateChild/CanLoad Feature Toggle Guard and the feature toggle is disabled.\n\nFor advanced scenarios you can use a combination of route guards AND redirects. E.G.\n\n```js\n...\nexport const routes: Routes = [\n  {\n    path: 'customer',\n    component: CustomerComponent,\n    canLoad: [NgxFeatureToggleRouteGuard],\n    canActivate: [NgxFeatureToggleRouteGuard],\n    canActivateChild: [NgxFeatureToggleRouteGuard],\n    // This is the featureToggle configuration for\n    // the parent component\n    data: {\n      featureToggle: ['enableCustomerPage'],\n      // If feature toggle is disabled, the user will be redirected to `/error` URL\n      redirectTo: '/error'\n    },\n    children: [\n      {\n        path: ':id',\n        component: CustomerDetailComponent,\n        // This is the featureToggle configuration for\n        // the child component. It can also use\n        // a combination of feature toggles\n        data: {\n          featureToggle: ['enableCustomerPage', '!enableChildrenNavigation'],\n          // If one (or all of them) of the feature toggle is disabled, the user will be redirected to `/customer-error` URL\n          // Note that you can use redirects for the main url and their children\n          redirectTo: '/customer-error'\n        },\n      },\n    ],\n  },\n];\n...\n```\n\n## Development\n\n### Run demo locally\n\n1. This project uses [Angular CLI](https://cli.angular.io/) as base. That means you just need to run `npm start` and access the link `http://localhost:4200` in your browser\n\n### Run tests\n\n1. Run `npm test` for run tests. In case you want to test using watch, please use `npm run tdd`\n\n### Publish\n\nthis project is using `np` package to publish, which makes things straightforward. EX: `np \u003cpatch|minor|major\u003e --contents=dist/ngx-feature-toggle`\n\n\u003e For more details, [please check np package on npmjs.com](https://www.npmjs.com/package/np)\n\n## Contribute\n\nFor any type of contribution, please follow the instructions in [CONTRIBUTING.md](https://github.com/willmendesneto/ngx-feature-toggle/blob/master/CONTRIBUTING.md) and read [CODE_OF_CONDUCT.md](https://github.com/willmendesneto/ngx-feature-toggle/blob/master/CODE_OF_CONDUCT.md) files.\n\n## Author\n\n**Wilson Mendes (willmendesneto)**\n\n- \u003chttps://twitter.com/willmendesneto\u003e\n- \u003chttp://github.com/willmendesneto\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwillmendesneto%2Fngx-feature-toggle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwillmendesneto%2Fngx-feature-toggle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwillmendesneto%2Fngx-feature-toggle/lists"}