npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@upplication/ng

v1.2.1

Published

ES7 decorators for lazy AngularJS devs

Downloads

8

Readme

@upplication/ng

AngularJS, but with decorators

NPM Version

Installation

$ npm install --save angular @upplication/ng

Take in mind that this library relies on the use of @Decorators syntax, so you maybe want to install something for handling that too. We'd recomend using babel alongside a decorators plugin:

Install babel

$ npm install --save-dev babel-cli \
    babel-preset-es2015 \
    babel-preset-es2016 \
    babel-preset-es2017 \
    babel-plugin-transform-decorators

.babelrc

{
  "presets": [
    "es2015",
    "es2016",
    "es2017"
  ],
  "plugins": [
    "transform-decorators"
  ]
}

Docs

@Injectable

@Injectable(name? : String)
class MyClass {}

Marks the decorated class as injectable, or in other words, an angular service. The name of the service will be the name of the class or the provided name to the decorator function. Also makes the class injectable via refenrece when using @Inject

Example

import { Injectable } from '@upplication/ng'

@Injectable()
export class HeroStoreService { ... }

@Injectable('HeroApi')
export class HeroApiService { ... }

// classic way
angular
    .module('app', [])
    .service('HeroService', HeroStoreService)
    .service('HeroApi', HeroApiService)

@Inject

@Inject(...dependencies : <String|Injectable>[])
class MyClass {}

Injects the class with the specified angular services and injectables. This is equivalent to adding the $inject property to the class or using the array injection notation ([ 'a', 'b', function(a, b) { .. } ]).

Every dependency passed as an argument must be either a service name, which can be an angular core service (like '$http') or a service provided by dependency module (like '$translate'), or the reference to a class already decorated with @Injectable.

The injected dependencies are passed to the constructor of the class.

Example

import { Injectable, Inject } from '@upplication/ng'

@Injectable()
export class ApiConfiguration { ... }

@Injectable()
@Inject('$http', ApiConfiguration)
export class ApiConsumer {
    constructor($http, apiConfiguration) {
        // Do something with the injections, usually store them locally
        this.$http = $http
        this.apiConfiguration = apiConfiguration
    }
}

@Injectable()
@Inject('$q', ApiConsumer)
export class HeroApi {
    constructor($q, apiConsumer) { ... }
}

// classic way
angular
    .module('app', [])
    .service('ApiConfiguration', ApiConfiguration)
    .service('ApiConsumer', [ '$http', 'ApiConfiguration', ApiConsumer ])
    .service('HeroApi', [ '$q', 'ApiConsumer', HeroApi ])

@Pipe

TODO

@Directive

@Directive({
    selector: string,
    services?: Inectable[],
    pipes?: Pipe[]
    directives?: <Directive|Component>[]
})
class MyClass {}

Registers a new directive with the object passed as argument being the directive definition and the decorated class the controller to be used by said directive.

The directive name must be provided as a selector property on the definition object and must be a kebab-case string representing the attribute name that would use this directive.

Also, any local service, pipe, or other directives being used by this directive must be specified as properties on the directive definition object as follows:

  • services: Array of @Injectable decorated classes. Don't include here services that come from angular core or module dependencies.
  • pipes: Array of @Pipe decorated classes. Don't include here filters that come from angular core or module dependencies.
  • directives: Array of @Directive or @Component decorated classes.

Example

import { Injectable, Inject } from '@upplication/ng'

@Directive({
    selector: 'fading-background',
    services: [
        HeroStoreService,
    ]
})
@Inject('$scope', '$element', '$attrs', HeroStoreService)
export class FadingBackgroundDirective {
    constructor($scope, $element, $attrs, heroStoreService) {
        // Set up $element listeners? maybe scope $watchers
    }

    $onDestroy() {
        // Dont forget to unregister your listeners :)
    }
}

// classic way
angular
    .module('app', [])
    // (...)
    .directive('fadingBackground', function() {
        return {
            scope: false,
            restrict: 'A',
            controller: [ 'HeroStoreService', FadingBackgroundDirectiveCtrl ],
            link: function(scope, element, attrs, ctrl) {
                element.on('$destroy', function() { ctrl.$onDestroy && ctrl.$onDestroy() })
            }
        }
    }])

@Component

@Component({
    selector: string,
    services?: Inectable[],
    pipes?: Pipe[]
    directives?: <Directive|Component>[]
})
class MyClass {}

Registers a new component with the object passed as argument being the component definition and the decorated class the controller of said component.

Also, any local service, pipe, or other directives being used by this directive must be specified as properties on the directive definition object as follows:

  • services: Array of @Injectable decorated classes. Don't include here services that come from angular core or module dependencies.
  • pipes: Array of @Pipe decorated classes. Don't include here filters that come from angular core or module dependencies.
  • directives: Array of @Directive or @Component decorated classes

Example

import { Component } from '@upplication/ng'

@Component({
    selector: 'hello-world',
    template: `Hello world, I'm {{ $ctrl.name }}`,
    styles: [],
    bindings: {
        name: '<'
    }
})
export class HelloWorldComponent { ... }

@Module

@Module({
    name: string,
    services?: Inectable[],
    pipes?: Pipe[]
    directives?: <Directive|Component>[]
})
class MyClass {}

Bundles a whole set of classes decorated with previous decorators into an actual angular.module. Prior to actually declaring the injectables, pipes, directives and components as dependencies of a Module, no real registration of said modules happen.

The decorator must be passed an object containing all the parts to be exposed and the module name itself as follows:

  • name: Name of the angular module
  • services: Array of @Injectable decorated classes to be bundled on this module
  • pipes: Array of @Pipe decorated classes. to be bundled on this module
  • directives: Array of @Directive or @Component decorated classes to be bundled in this module
  • requires: Array of angular.module-s or angular.module names that this module requires to work.

If the decorated class provides a static config() method, that method will be executed on module config phase.

If the decorated class provides a static run() method, that method will be executed on module run phase.

Example

@Module({
    name: 'app',
    services: [
        HeroApiService,
        HeroStoreService,
        ApiConsumer,
    ],
    pipes: [
        UppercasePipe,
        CamelCasePipe,
    ],
    directives: [
        FadingBackgroundDirective,
        HelloWorldComponent,
    ],
})
export class MyApp {
    static config() {
        console.log('Config!')
    }

    static run() {
        console.log('Running!')
    }
}

@Config

@Config()

Allows to declare a function inside a class decorated with @Module as a config step that must be run through angular.config. Usual angular policies about injecting providers apply as usual here.

Example

@Module({ /*...*/ })
class MyClass {
    @Config()
    @Inject('$apiProvider')
    configApi($apiProvider) { /*...*/ }
}

@Run

@Run()

Allows to declare a function inside a class decorated with @Module as a run step that must be run through angular.run.

Example

@Module({ /*...*/ })
class MyClass {
    @Run()
    @Inject('heroAp')
    sayHello(heroApi) {
        console.log('Hello :)')
    }
}

Mix

class MyClass extends Mix(MySuperClass, MyMixin1, MyMixin2) { /*...*/ }

Declare mixins chains and a superclass for mixin generator functions. See docs at the Mixin file for detailed information.

Example

import { Mix, Mixin } from '@upplication/ng'

const MyMixin1 = Mixin(superclass => class extends superclass {
    /* Awesome Mixin */
})
const MyMixin2 = Mixin(superclass => class extends superclass {
    /* Much more awesome Mixin */
})

class MyClass1 extends Mix(MyMixin1) { /*...*/ }
class MyClass2 extends Mix(MyClass1, MyMixin2) { /*...*/ }

t### @$apply

class MyClass {
    @$apply
    async myAsyncFn() {
        // ...
    }
}

Helper decorator for triggering a $rootScope.$apply() after the decorated function. This is specially useful when you are using ES6+ features (like async/await).

Example

import { Component, $async } from '@upplication/ng'

@Component({
    selector: 'hello-world',
    template: `Hello world, I'm {{ $ctrl.name }}`,
    styles: [],
    bindings: {
        name: '<'
    }
})
export class HelloWorldComponent {
    constructor() {...}

    @$apply
    async someAsyncAction() {
        await this.request(...)
    }
}

@actionLock

class MyClass {
    @actionLock('action1')
    async doStuff() { /* ... */ }
}

Helper decorator for setting up interlocks between different controller functions. This is specially useful when exposing async controller functions that should not be able to be called more than once while the associated promise has not been resolved yet. You can use isActionLocked(...) afterwards to check action status.

Example

import { Component, $async, actionLock, isActionLocked } from '@upplication/ng'

@Component({
    selector: 'hello-world',
    template: `Hello world, I'm {{ $ctrl.name }}`,
    styles: [],
    bindings: {
        name: '<'
    }
})
export class HelloWorldComponent {
    constructor() {...}

    @actionLock('inviteRequest')
    async acceptInvite() { /* ... */ }

    @actionLock('inviteRequest')
    async rejectInvite() { /* ... */ }

    isInviteResponsePending() {
        return isActionLocked(this, 'inviteRequest')
    }
}

In the above code will make calls to acceptInvite or rejectInvite check if a lock for the action inviteRequest is active. If the lock is enabled the function call will do nothing. If the lock was not enabled, it will be enabled (preventing future calls from running) and the actual function will be invoked and will release the lock at the end of such invocation.