{"id":15184846,"url":"https://github.com/fabric8-ui/ngx-feature-flag","last_synced_at":"2025-10-02T00:31:39.903Z","repository":{"id":65424543,"uuid":"138324550","full_name":"fabric8-ui/ngx-feature-flag","owner":"fabric8-ui","description":":sparkles: Feature flag angular library :checkered_flag:","archived":true,"fork":false,"pushed_at":"2019-01-14T15:08:14.000Z","size":435,"stargazers_count":5,"open_issues_count":0,"forks_count":7,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-01-06T11:45:58.372Z","etag":null,"topics":["angular","angular4","feature-flags","feature-toggles"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fabric8-ui.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}},"created_at":"2018-06-22T16:25:52.000Z","updated_at":"2023-01-28T09:07:22.000Z","dependencies_parsed_at":"2023-01-23T10:55:19.735Z","dependency_job_id":null,"html_url":"https://github.com/fabric8-ui/ngx-feature-flag","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabric8-ui%2Fngx-feature-flag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabric8-ui%2Fngx-feature-flag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabric8-ui%2Fngx-feature-flag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabric8-ui%2Fngx-feature-flag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fabric8-ui","download_url":"https://codeload.github.com/fabric8-ui/ngx-feature-flag/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234916159,"owners_count":18906643,"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","angular4","feature-flags","feature-toggles"],"created_at":"2024-09-27T17:41:00.381Z","updated_at":"2025-10-02T00:31:39.577Z","avatar_url":"https://github.com/fabric8-ui.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://ci.centos.org/buildStatus/icon?job=devtools-ngx-feature-flag-npm-publish-build-master)](https://ci.centos.org/job/devtools-ngx-feature-flag-npm-publish-build-master)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n# ngx-feature-flag\n\n## Purpose\nThe main motivation for doing feature toggling is to decouple the process for deploying code to production and releasing new features. This helps reducing risk, and allow us to easily manage which features to enable\n\nFeature toggles decouple deployment of code from release of new features. For more insight, read [Martin Fowler's](https://martinfowler.com/bliki/FeatureToggle.html) and [Pete Hodgson's Feature flag, A/B testing article](https://martinfowler.com/articles/feature-toggles.html)\n\nThe fabric8 feature toggles is based on [unleash](https://github.com/Unleash/unleash) upstream open source project. \n* [fabric8-toggles](https://github.com/fabric8-services/fabric8-toggles) is where the server and its DB run.\n* [fabric8-toggles-service](https://github.com/fabric8-services/fabric8-toggles-service) is the service used by fabric8-ui to turn on/off and roll out features. `fabric8-ui` targets `fabric8-toggles-service`.\n* [fabric8-ui in feature-flag module](https://github.com/fabric8-ui/fabric8-ui/tree/master/src/app/feature-flag) is where the angular components and services for toggles are.\n\n## Admin console\nAdmin consoles are available here:\n* [Prod UI](http://admin-dsaas-production.09b5.dsaas.openshiftapps.com/toggles/)\n* [Preview UI](https://adminproxy.prod-preview.openshift.io/toggles/)\n\n\u003e NOTE: atm, we don't have any sync mechanism between the 2 instances. This is 2 separate DB.\n\n\n### How to login?\nTo login to toggles admin console, we use GitHub authentication and we provide some authorisation checking that your user is part of some organisation.\n* You will be prompted to authenticate though GH.\n* If not yet part of the [RHDT organization](https://github.com/rhdt-dev), please open a pull request to the UserDB (under VPN; Check DevGuide for details)\n* If you're already part of the [RHDT organization](https://github.com/rhdt-dev) but not a member of either [prod-preview](https://github.com/orgs/rhdt-dev/teams/toggles-admin-preprod/members) or [prod team](https://github.com/orgs/rhdt-dev/teams/toggles-admin-prod/members), contact some admins in mattermost #fabric8-platform and ask them to add you. You will need to be an internal user to be granted access. Once granted, try again.\n\n### How to logout?\nSearch for `Sign out` in the admin console. You will be logged out of fabric8-toggles admin ui but not logged out of GH. If you want to login with a different GH account, logout of GH.\n\n## Getting started\n\n* You can import the lib in your application:\n\n`npm install ngx-feature-flag`\n \n## Build \n \n* Pre-requisites\n  * node v8.9.1+ (required by anuglar-cli 6+)\n  * npm 5.5.1\n\nThis angular library is built using [angular-cli](https://github.com/angular/angular-cli/wiki)'s workspace.\nThe main application is the demo app. The library source is under [/project/ngx-feature-flag](/project/ngx-feature-flag)\n\n* Install the dependencies\n \n```\nnpm i\n```\n \n* Build library \u0026 demo app\n```\nnpm run build\n```\n\n* Run the library tests\n \n```\nnpm test\n```\n \n\u003e NOTE: to run the library test in watch mode: `npm run test:lib:dev`\n\n* Fix lint errors (package import for ex)\n\n```\nnpm run lint:fix\n```\n\n## Run the demo\n\n```shell\nnpm i\nnpm run build\nnpm start\n```\n\nOpen your browser on http://localhost:4200/\n\n## Usage\n\n### FeatureTogglesService\nUse the service directly to request the Feature.\n#### use case 1: My feature is a module accessible by routing\nTake the new launchpad wizard as an example:\n* In admin ui, add your new feature with a `featureName` (here `AppLauncher`), associate a `enableByLevel` strategy, enter the `level` parameter (`internal`, `experimental`, `beta`, `released`).\n* [routing file](https://github.com/fabric8-ui/fabric8-ui/commit/b7a519c884829acc24b5c890608516e777d7e004#diff-959f71d9b4ce6d41e637aaf363c42a18): add `FeatureFlagResolver`(responsible to query the `fabric8-toggles-service`, also specify the name of your feature in `featureName`. Here `AppLauncher` should exactly match the feature name (ie: this is the external key between fabric8-ui and fabric8-toggles) defined in fabric8-toggles admin UI.\n```\n  {\n    path: '_applauncher',\n    resolve: {\n      featureFlagConfig: FeatureFlagResolver\n    },\n    loadChildren: './app-launcher/app-launcher.module#AppLauncherModule',\n    data: {\n      title: 'App Launcher',\n      featureName: 'AppLauncher'\n    }\n  },\n```\n\n#### use case 2: My feature is accessible on to a given set of user emails\nAtm we have 2 rollout strategies to use with `fabric8-toggles-service`:\n\n* Enable by level\n`enableByLevel` is the most commonly used. It allows to tag a feature for a particular level. Feature flag level are: `internal`, `experimental`, `beta`, `released`.\n  * `internal` will only show it to accounts with an @redhat.com email. It will have a notification on the screen: \"This feature is open to Red Hat users only. You can manage pre-production features on your profile page.\" \n  * `experimental` will be \"This feature is experimental. You can manage pre-production features on your profile page.\" \n  * `beta` notification will be \"This feature is in beta. You can manage pre-production features on your profile page.\" \n  * `released` makes the feature default for everyone.\n\n\u003e NOTE: Anonymous user can only see the `released` state. For other level, you need to be logged-in.\n\n* Enable by emails.\n`enableByEmails` is used for a work in progress feature. You can create a feature with the strategy `emableByEmails` and then list the different users' emails of the other developers you want to collaborate with on this WIP feature.\n\nFor example, while working on `new dashboard` feature, Adam wanted to share the new dashboard only with a group of UI developers. Easy way is to used the `enableByEmails`. Once the feature is ready, Adam could remove the strategy `enableByEmails` and replace it with a strategy `enableByLevel` with a level of `internal` to start with.\n\n### Compoment\n`ngx-feature-flag` provides 2 components to help you hide and show your features under feature-flag.\n\n\u003e \u003cb\u003eTIP: As a best practise,\u003c/b\u003e if you know a page of your app will have several feature flag, group them per page. We use a naming convention:\n`Page.MyFeature` where `Page` is the name you use in the FeatureFlagResolver. \n\n#### use case 1: My feature is a component I want to hide/show\nFor example, let's hide `EnvironmentWidgetComponent` which is shown in a `Environment` page. Follow the best practices and name your feature `Environment.Test`. If your don't want to \"group\" features, you can call it simply `Test`.\n* In unleash admin ui, add your new feature with a `featureName` (here `Environment.Test`), associate a `enableByLevel` strategy, enter the `level` parameter (`internal`, `experimental`, `beta`, `released`). If this level (for ex: experimental) is below your user-consent level (for ex: beta), you won't see the component. \n* In your [routing file](https://github.com/fabric8-ui/fabric8-ui/commit/b7a519c884829acc24b5c890608516e777d7e004#diff-959f71d9b4ce6d41e637aaf363c42a18): \nadd `FeatureFlagResolver`(responsible to query the `fabric8-toggles-service`, also specify the name of \nyour feature in `featureName`. Here `Environment.Test` should exactly match the feature name \n(ie: this is the external key between fabric8-ui and fabric8-toggles) defined in fabric8-toggles admin UI.\nNote: this step is optional if you do not group your component per page.\n* In your page or component template:\n```\n\u003cf8-feature-toggle featureName=\"Environment.Test\" [userLevel]=\"user\"\u003e\u003c/f8-feature-toggle\u003e\n\u003cng-template #user\u003e\n  YOUR NEW HTML\n\u003c/ng-template\u003e\n```\n* In your Module, import `FeatureFlagModule`:\n```\n@NgModule({\n  imports: [CommonModule, FormsModule, RouterModule, MomentModule, FeatureFlagModule ],\n  declarations: [EnvironmentWidgetComponent],\n  exports: [EnvironmentWidgetComponent]\n})\nexport class EnvironmentWidgetModule { }\n```\n\n\u003e NOTE: the component is hidden but still initialized.\n\n#### use case 2: My feature is a refactored component I want to hide/show\nSimilar to precedent section. You put the new code in the HTML element that content `user-level` and the old code in `default-level`.\n\nFor example:\n\n```\n\u003cf8-feature-toggle featureName=\"Analyze.newSpaceDashboard\" [userLevel]=\"user\" [defaultLevel]=\"default\"\u003e\u003c/f8-feature-toggle\u003e\n\u003cng-template #user\u003e\n  YOUR NEW HTML\n\u003c/ng-template\u003e\n\u003cng-template #default\u003e\n  YOUR OLD HTML\n\u003c/ng-template\u003e\n```\n\n#### use case 3: My feature is a component I want to dynamically load\nThis use case could be while the feature is under development and you want to make sure loading the component will not break the whole UI.\n\nFor example, let's dynamically load `EnvironmentWidgetComponent` to carry-on with the same example. but now we don't want to just hide the component, we want to make sure the component code is not loaded at all (this could be useful if for some reasons the component code may cause runtime failure).\n* In unleash admin ui, add your new feature with a `featureName` (here `Environment.Test`), associate a `enableByLevel` strategy, enter the `level` parameter (`internal`, `experimental`, `beta`, `released`). If this level (for ex: experimental) is below your user-consent level (for ex: beta), you won't see the component. \n* In `analyze-overview.component.html` template, replace `\u003cfabric8-environment-widget /\u003e` by `\u003cf8-feature-toggle-loader featureName=\"Environment.Test\"\u003e\u003c/f8-feature-toggle-loader\u003e` where `Environment.Test` is the name of the feature. Choose an meaningful name like: `env.widget`. For test purpose here we reuse `Environment.Test`.\n* In the module associated to your dynamically loaded component add an `entryComponents`. For ex, in `analyze-overview.module.ts`:\n```\n@NgModule({\n  imports: [\n    CommonModule,\n    AnalyzeOverviewRoutingModule,\n    FeatureFlagModule,\n    FormsModule,\n    EditSpaceDescriptionWidgetModule,\n    AnalyticalReportWidgetModule,\n    CreateWorkItemWidgetModule,\n    AddCodebaseWidgetModule,\n    PipelinesWidgetModule,\n    EnvironmentWidgetModule,\n    ForgeWizardModule,\n    ModalModule.forRoot()\n  ],\n  declarations: [AnalyzeOverviewComponent],\n  entryComponents: [EnvironmentWidgetComponent]\n})\nexport class AnalyzeOverviewModule {\n  constructor(http: Http) { }\n}\n```\nBecause we use Feature-flag, we've also added `FeatureFlagModule` in the imports of the module.\n\u003e Note: For more information on `entryComponents` read angular docs on [entryComponents](https://angular.io/guide/entry-components) and [dynamic component load](https://angular.io/guide/dynamic-component-loader).\n\n* Tell fabric8-ui which feature match which component. In `src/app/feature-flag.mapping.ts`, add a `case` in `convertFeatureNameToComponent` method:\n```\n  convertFeatureNameToComponent(name: string): Type\u003cany\u003e {\n    switch (name) {\n      case 'Environment.Test': {\n        return EnvironmentWidgetComponent;\n      }\n      default: {\n        return null;\n      }\n    }\n  }\n```\n\n\n## Demo\n\nBetter than just usage you want to see it in action? run the demo:\n* with direct access to [prod-preview]() uncomment []()\n* with mock data (default option)\n\n\n```\nnpm run build:demo\nnpm run start:demo\n\n```\n\nGo to http://localhost:8001 \n\n## Release\n\n* pre-requisites\nLogin to [npmjs central repo](https://www.npmjs.com/) with your credential (you should be owner of the library).\n\n* build `ngx-feature-flag` as a npm library\n\n```\nnpm run build   \n```\n\n* publish\n```\nnpm publish dist\n```\n\n\u003e Note: semantic release are done via fabric8cd using `semantic-release`\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffabric8-ui%2Fngx-feature-flag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffabric8-ui%2Fngx-feature-flag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffabric8-ui%2Fngx-feature-flag/lists"}