{"id":20895022,"url":"https://github.com/upplication/ng","last_synced_at":"2025-10-24T19:16:59.499Z","repository":{"id":68973203,"uuid":"85417794","full_name":"Upplication/ng","owner":"Upplication","description":"ES7 Decorators for lazy AngularJS developers","archived":false,"fork":false,"pushed_at":"2017-06-05T12:24:33.000Z","size":33,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-27T11:47:12.938Z","etag":null,"topics":["angular","angularjs","babel","decorators"],"latest_commit_sha":null,"homepage":null,"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/Upplication.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-18T17:01:29.000Z","updated_at":"2018-09-27T15:28:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"716d99e1-6746-4020-849c-85923b06d949","html_url":"https://github.com/Upplication/ng","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Upplication%2Fng","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Upplication%2Fng/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Upplication%2Fng/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Upplication%2Fng/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Upplication","download_url":"https://codeload.github.com/Upplication/ng/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253840351,"owners_count":21972466,"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","angularjs","babel","decorators"],"created_at":"2024-11-18T10:24:29.913Z","updated_at":"2025-10-24T19:16:54.455Z","avatar_url":"https://github.com/Upplication.png","language":"JavaScript","readme":"# @upplication/ng\n_AngularJS, but with decorators_\n\n[![NPM Version][npm-image]][npm-url]\n\n## Installation\n```\n$ npm install --save angular @upplication/ng\n```\n\nTake in mind that this library relies on the use of `@Decorators` syntax,\nso you maybe want to install something for handling that too. We'd recomend\nusing [babel](https://babeljs.io/) alongside\n[a decorators plugin](https://babeljs.io/docs/plugins/transform-decorators/):\n\n**Install babel**\n```\n$ npm install --save-dev babel-cli \\\n    babel-preset-es2015 \\\n    babel-preset-es2016 \\\n    babel-preset-es2017 \\\n    babel-plugin-transform-decorators\n```\n**.babelrc**\n```json\n{\n  \"presets\": [\n    \"es2015\",\n    \"es2016\",\n    \"es2017\"\n  ],\n  \"plugins\": [\n    \"transform-decorators\"\n  ]\n}\n```\n\n## Docs\n\n* [@Injectable](#injectable)\n* [@Inject](#inject)\n* [@Pipe](#pipe)\n* [@Directive](#directive)\n* [@Component](#component)\n* [@Module](#module)\n* [@Config](#config)\n* [@Run](#run)\n* [@$apply](#apply)\n* [@actionLock](#actionLock)\n\n### @Injectable\n```js\n@Injectable(name? : String)\nclass MyClass {}\n```\nMarks the decorated class as injectable, or in other words, an angular service.\nThe name of the service will be the name of the class or the provided name to\nthe decorator function. Also makes the class injectable via refenrece when\nusing `@Inject`\n\n#### Example\n```js\nimport { Injectable } from '@upplication/ng'\n\n@Injectable()\nexport class HeroStoreService { ... }\n\n@Injectable('HeroApi')\nexport class HeroApiService { ... }\n\n// classic way\nangular\n    .module('app', [])\n    .service('HeroService', HeroStoreService)\n    .service('HeroApi', HeroApiService)\n```\n\n### @Inject\n```js\n@Inject(...dependencies : \u003cString|Injectable\u003e[])\nclass MyClass {}\n```\nInjects the class with the specified angular services and injectables. This is\nequivalent to adding the `$inject` property to the class or using the array\ninjection notation (`[ 'a', 'b',  function(a, b) { .. } ]`).\n\nEvery dependency passed as an argument must be either a service name, which can\nbe an angular core service (like `'$http'`) or a service provided by dependency\nmodule (like `'$translate'`), or the reference to a class already decorated\nwith `@Injectable`.\n\nThe injected dependencies are passed to the constructor of the class.\n\n#### Example\n```js\nimport { Injectable, Inject } from '@upplication/ng'\n\n@Injectable()\nexport class ApiConfiguration { ... }\n\n@Injectable()\n@Inject('$http', ApiConfiguration)\nexport class ApiConsumer {\n    constructor($http, apiConfiguration) {\n        // Do something with the injections, usually store them locally\n        this.$http = $http\n        this.apiConfiguration = apiConfiguration\n    }\n}\n\n@Injectable()\n@Inject('$q', ApiConsumer)\nexport class HeroApi {\n    constructor($q, apiConsumer) { ... }\n}\n\n// classic way\nangular\n    .module('app', [])\n    .service('ApiConfiguration', ApiConfiguration)\n    .service('ApiConsumer', [ '$http', 'ApiConfiguration', ApiConsumer ])\n    .service('HeroApi', [ '$q', 'ApiConsumer', HeroApi ])\n\n```\n\n### @Pipe\n**TODO**\n\n### @Directive\n```js\n@Directive({\n    selector: string,\n    services?: Inectable[],\n    pipes?: Pipe[]\n    directives?: \u003cDirective|Component\u003e[]\n})\nclass MyClass {}\n```\nRegisters a new directive with the object passed as argument being the\n[directive definition](https://docs.angularjs.org/guide/directive) and\nthe decorated class the controller to be used by said directive.\n\nThe directive name must be provided as a *selector* property on the\ndefinition object and *must* be a _kebab-case_ string representing the\nattribute name that would use this directive.\n\nAlso, any local service, pipe, or other directives being used by this\ndirective must be specified as properties on the directive definition object\nas follows:\n* **services**: Array of `@Injectable` decorated classes. *Don't* include here\n    services that come from angular core or module dependencies.\n* **pipes**: Array of `@Pipe` decorated classes. *Don't* include here\n    filters that come from angular core or module dependencies.\n* **directives**: Array of `@Directive` or `@Component` decorated classes.\n\n#### Example\n```js\nimport { Injectable, Inject } from '@upplication/ng'\n\n@Directive({\n    selector: 'fading-background',\n    services: [\n        HeroStoreService,\n    ]\n})\n@Inject('$scope', '$element', '$attrs', HeroStoreService)\nexport class FadingBackgroundDirective {\n    constructor($scope, $element, $attrs, heroStoreService) {\n        // Set up $element listeners? maybe scope $watchers\n    }\n\n    $onDestroy() {\n        // Dont forget to unregister your listeners :)\n    }\n}\n\n// classic way\nangular\n    .module('app', [])\n    // (...)\n    .directive('fadingBackground', function() {\n        return {\n            scope: false,\n            restrict: 'A',\n            controller: [ 'HeroStoreService', FadingBackgroundDirectiveCtrl ],\n            link: function(scope, element, attrs, ctrl) {\n                element.on('$destroy', function() { ctrl.$onDestroy \u0026\u0026 ctrl.$onDestroy() })\n            }\n        }\n    }])\n```\n\n### @Component\n```js\n@Component({\n    selector: string,\n    services?: Inectable[],\n    pipes?: Pipe[]\n    directives?: \u003cDirective|Component\u003e[]\n})\nclass MyClass {}\n```\nRegisters a new component with the object passed as argument being the\n[component definition](https://docs.angularjs.org/guide/component) and\nthe decorated class the controller of said component.\n\nAlso, any local service, pipe, or other directives being used by this\ndirective must be specified as properties on the directive definition object\nas follows:\n* **services**: Array of `@Injectable` decorated classes. *Don't* include here\n    services that come from angular core or module dependencies.\n* **pipes**: Array of `@Pipe` decorated classes. *Don't* include here\n    filters that come from angular core or module dependencies.\n* **directives**: Array of `@Directive` or `@Component` decorated classes\n\n#### Example\n```js\nimport { Component } from '@upplication/ng'\n\n@Component({\n    selector: 'hello-world',\n    template: `Hello world, I'm {{ $ctrl.name }}`,\n    styles: [],\n    bindings: {\n        name: '\u003c'\n    }\n})\nexport class HelloWorldComponent { ... }\n```\n\n### @Module\n```js\n@Module({\n    name: string,\n    services?: Inectable[],\n    pipes?: Pipe[]\n    directives?: \u003cDirective|Component\u003e[]\n})\nclass MyClass {}\n```\nBundles a whole set of classes decorated with previous decorators into\nan actual `angular.module`. Prior to actually declaring the injectables,\npipes, directives and components as dependencies of a Module, no real\nregistration of said modules happen.\n\nThe decorator must be passed an object containing all the parts to be\nexposed and the module name itself as follows:\n* **name**: Name of the angular module\n* **services**: Array of `@Injectable` decorated classes to be bundled on this\n    module\n* **pipes**: Array of `@Pipe` decorated classes.  to be bundled on this\n    module\n* **directives**: Array of `@Directive` or `@Component` decorated classes to be\n    bundled in this module\n* **requires**: Array of `angular.module`-s or `angular.module` names that this\n    module requires to work.\n\nIf the decorated class provides a static `config()` method, that method will be\nexecuted on module config phase.\n\nIf the decorated class provides a static `run()` method, that method will be\nexecuted on module run phase.\n\n#### Example\n```js\n@Module({\n    name: 'app',\n    services: [\n        HeroApiService,\n        HeroStoreService,\n        ApiConsumer,\n    ],\n    pipes: [\n        UppercasePipe,\n        CamelCasePipe,\n    ],\n    directives: [\n        FadingBackgroundDirective,\n        HelloWorldComponent,\n    ],\n})\nexport class MyApp {\n    static config() {\n        console.log('Config!')\n    }\n\n    static run() {\n        console.log('Running!')\n    }\n}\n```\n\n\n### @Config\n```\n@Config()\n```\n\nAllows to declare a function inside a class decorated with `@Module` as a\nconfig step that must be run through `angular.config`. Usual angular policies\nabout injecting providers apply as usual here.\n\n#### Example\n\n```js\n@Module({ /*...*/ })\nclass MyClass {\n    @Config()\n    @Inject('$apiProvider')\n    configApi($apiProvider) { /*...*/ }\n}\n```\n\n### @Run\n```\n@Run()\n```\n\nAllows to declare a function inside a class decorated with `@Module` as a\nrun step that must be run through `angular.run`.\n\n#### Example\n\n```js\n@Module({ /*...*/ })\nclass MyClass {\n    @Run()\n    @Inject('heroAp')\n    sayHello(heroApi) {\n        console.log('Hello :)')\n    }\n}\n```\n\n### Mix\n```js\nclass MyClass extends Mix(MySuperClass, MyMixin1, MyMixin2) { /*...*/ }\n```\n\nDeclare mixins chains and a superclass for mixin generator functions.\nSee docs at the [Mixin file](src/helpers/Mixin.js) for detailed information.\n\n#### Example\n```js\nimport { Mix, Mixin } from '@upplication/ng'\n\nconst MyMixin1 = Mixin(superclass =\u003e class extends superclass {\n    /* Awesome Mixin */\n})\nconst MyMixin2 = Mixin(superclass =\u003e class extends superclass {\n    /* Much more awesome Mixin */\n})\n\nclass MyClass1 extends Mix(MyMixin1) { /*...*/ }\nclass MyClass2 extends Mix(MyClass1, MyMixin2) { /*...*/ }\n\n```\n\nt### @$apply\n```js\nclass MyClass {\n    @$apply\n    async myAsyncFn() {\n        // ...\n    }\n}\n```\nHelper decorator for triggering a `$rootScope.$apply()` after the decorated\nfunction. This is specially useful when you are using ES6+ features (like\nasync/await).\n\n#### Example\n```js\nimport { Component, $async } from '@upplication/ng'\n\n@Component({\n    selector: 'hello-world',\n    template: `Hello world, I'm {{ $ctrl.name }}`,\n    styles: [],\n    bindings: {\n        name: '\u003c'\n    }\n})\nexport class HelloWorldComponent {\n    constructor() {...}\n\n    @$apply\n    async someAsyncAction() {\n        await this.request(...)\n    }\n}\n```\n\n### @actionLock\n```js\nclass MyClass {\n    @actionLock('action1')\n    async doStuff() { /* ... */ }\n}\n```\nHelper decorator for setting up interlocks between different controller\nfunctions. This is specially useful when exposing async controller functions\nthat should not be able to be called more than once while the associated\npromise has not been resolved yet. You can use `isActionLocked(...)` afterwards\nto check action status.\n\n#### Example\n```js\nimport { Component, $async, actionLock, isActionLocked } from '@upplication/ng'\n\n@Component({\n    selector: 'hello-world',\n    template: `Hello world, I'm {{ $ctrl.name }}`,\n    styles: [],\n    bindings: {\n        name: '\u003c'\n    }\n})\nexport class HelloWorldComponent {\n    constructor() {...}\n\n    @actionLock('inviteRequest')\n    async acceptInvite() { /* ... */ }\n\n    @actionLock('inviteRequest')\n    async rejectInvite() { /* ... */ }\n\n    isInviteResponsePending() {\n        return isActionLocked(this, 'inviteRequest')\n    }\n}\n```\n\nIn the above code will make calls to `acceptInvite` or `rejectInvite` check if\na lock for the action  `inviteRequest` is active. If the lock is enabled the\nfunction call will do nothing. If the lock was not enabled, it will be enabled\n(preventing future calls from running) and the actual function will be invoked\nand will release the lock at the end of such invocation.\n\n[npm-image]: https://img.shields.io/npm/v/@upplication/ng.svg\n[npm-url]: https://npmjs.org/package/@upplication/ng\n[travis-image]: https://img.shields.io/travis/upplication/ng/master.svg\n[travis-url]:  https://travis-ci.org/upplication/ng\n[coveralls-image]: https://img.shields.io/coveralls/upplication/ng/master.svg\n[coveralls-url]: https://coveralls.io/r/upplication/ng?branch=master","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fupplication%2Fng","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fupplication%2Fng","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fupplication%2Fng/lists"}