Skip to content

Instantly share code, notes, and snippets.

@danharper
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danharper/0ce7298d14b569ac3aa3 to your computer and use it in GitHub Desktop.
Save danharper/0ce7298d14b569ac3aa3 to your computer and use it in GitHub Desktop.
ngBridge - wrap your Angular modules to support ES6 classes, and stricter assurances of DI
export function ngBridged(name, deps) {
return ngBridge(angular.module(name, deps))
}
export function ngBridge(ngModule) {
const register = (type, ...args) => ngBridge(ngModule[type](...args))
const injectable = type => (name, injectableFunc) => register(type, name, ngInject(injectableFunc))
const pass = type => (...args) => register(type, ...args)
return {
component: (...args) => register('directive', ...ngComponent(...args)),
directive: (...args) => this.component(...args),
controller: injectable('controller'),
service: injectable('service'),
factory: injectable('factory'),
provider: injectable('provider'),
filter: injectable('filter'),
animation: injectable('animation'),
config: pass('config'),
run: pass('run'),
value: pass('value'),
constant: pass('constant'),
routes: router => register('config', ['$stateProvider', $sp => router($sp.state)])
}
}
export function ngClass(injectableClass) {
return [...getInjects(injectableClass), (...injectedArgs) => new injectableClass(...injectedArgs)]
}
export function ngInject(injectableFunc) {
if (Array.isArray(injectableFunc)) {
return injectableFunc
}
else {
return [...getInjects(injectableFunc), injectableFunc]
}
}
export function ngComponent(name, component = null) {
if ( ! component) return ngComponent(null, name)
const ddo = component.ddo()
const directive = () => {
return {
...ddo,
scope: ddo.bind,
bindToController: true,
controller: ngInject(component),
controllerAs: ddo.name
}
}
return [(name || ddo.name), directive]
}
function getInjects(func) {
return func.ngInject ? func.ngInject() : []
}
// Modules
////////////////////////////////////
// you can full on replace the angular.module call:
import {ngBridged} from 'ngBridge'
ngBridged('my.module.name', [])
// or wrap your module:
import {ngBridge} from 'ngBridge'
ngBridge(angular.module('my.module.name', []))
// Controllers
////////////////////////////////////
// an injectable ES6 controller:
class BooksListController {
// define dependencies in static ngInject methods, instead of the $inject property or array syntax
static ngInject() {
return ['$http']
}
constructor($http) {
}
}
// registering on your module:
.controller('BooksListController', BooksListController) // on an ngBridge-wrapped module
.controller('BooksListController', ngInject(BooksListController)) // on non-wrapped module
// Components (Directives)
////////////////////////////////////
// a new directive (you can also use ngInject on here)
class BookComponent {
static ddo() {
return {
name: 'book', // name inside template & external name (<book></book>)
bind: {
title: '@'
},
template: `<strong>Name: {{book.title}}</strong>
<button ng-click="book.share()">Share!</button>`
}
}
share() {
alert(`Sharing book titled ${this.title}`)
}
}
// registering on your module:
.component(BookComponent) // registering with self-assigned name
.component('movie', BookComponent) // registering named <movie></movie> instead
.directive(...ngComponent(BookComponent)) // on a non-wrapped module
.directive(...ngComponent('movie', BookComponent)) // on a non-wrapped module, naming as <movie></movie>
// Services etc.
////////////////////////////////////
class MyService {
static ngInject() {
return ['$http']
}
constructor(thisisHttp) {
}
doSomething() {
}
}
// registering on your module:
.service('myService', MyService)
.service('myService', ngInject(MyService)) // non-wrapped module
// this still works:
.service('myService', ['$http', $http => {
// ...
}])
// but this won't (we're enforcing named DI)
.service('myService', $http => {
// $http is undefined
})
// Classes for config/run etc.? sure!
////////////////////////////////////
class DoSomethingForConfig {
static ngInject() {
return ['$stateProvider']
}
constructor($stateProvider) {
// ...
}
}
// registering:
.config(ngClass(DoSomethingForConfig)) // works either wrapped or not
// Routing (only included in this preview, it's the UI Router)
////////////////////////////////////
.router(state => {
state('home', {
url: '/',
template: 'Hello, World!'
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment