Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@vardius
Last active February 19, 2016 14:29
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 vardius/e7f5d55c21f846577bba to your computer and use it in GitHub Desktop.
Save vardius/e7f5d55c21f846577bba to your computer and use it in GitHub Desktop.
ES6 Angular OO Aproach
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
//Location in the `filters` directory
//This way `Loader class will find it.
export default function checkmark() {
return function(input) {
return input ? '\u2713' : '\u2718';
};
}
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
//Location in the `constants` directory
//This way `Loader class will find it.
export default class Settings {
constructor() {
this.url = "";
this.clientId = '';
this.clientSecret = '';
this.port = "80";
}
}
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
//Location in the `directives` directory
//This way `Loader class will find it.
class MyDirective {
constructor($interval) {
'ngInject';
this.template = '<div>I\'m a directive!</div>';
this.restrict = 'E';
this.scope = {};
this.$interval = $interval;
}
compile(tElement) {
tElement.css('position', 'absolute');
}
link(scope, element) {
this.$interval(() => this.move(element), 1000);
}
move(element) {
element.css('left', (Math.random() * 500) + 'px');
element.css('top', (Math.random() * 500) + 'px');
}
}
MyDirective.$inject = ['$interval'];
export default MyDirective;
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
//Location in the `factories` directory
//This way `Loader class will find it.
export default class ThingFactory {
constructor($timeout) {
this.$timeout = $timeout;
}
newThing() {
console.log('Getting a new Thing...');
return this.$timeout(() => new Thing(), 1000);
}
}
ThingFactory.$inject = ['$timeout'];
export default ThingFactory;
/**(c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
//Location in the `factories` directory
//This way `Loader class will find it.
export default class Model {
constructor($resource, url) {
this.$resource = $resource;
this.url = url;
this.resource = this.getResource();
}
getAll(params) {
let model = this.resource.query((typeof params === 'undefined' ? {} : params));
return this.returnPromise(model);
}
getById(id) {
let model = this.resource.get({id: id});
return this.returnPromise(model);
}
create(data) {
let model = new this.resource(data);
return model.$save();
}
update(id, data) {
data.id = id;
var model = new this.resource(data);
return model.$update();
}
remove(id) {
var data = {id: id};
var model = new this.resource(data);
return model.$delete();
}
getResource() {
return this.$resource(this.url, {id: '@id'}, {
'update': {
method: 'PUT'
},
'get': {
method: 'GET'
},
'save': {
method: 'POST'
},
'query': {
method: 'GET'
},
'remove': {
method: 'DELETE'
},
'delete': {
method: 'DELETE'
}
});
}
static returnPromise(object) {
return object.$promise.then(function (result) {
return result;
});
}
/**
* Important method!
* When class located inside `factories` directory contains this method,
* will be registered as service module but WORKS AS FACTORY.
* This is more correct way to register factories!
*
* @param $resource
* @param Settings
* @returns {Function}
*/
static factory($resource) {
'ngInject';
return (url) => {
return new Model($resource, url);
}
}
}
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
//Location in the `components` directory
//This way `Loader class will find it.
export default class navHeader {
constructor() {
this.templateUrl = 'components/header.html';
}
}
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
//Location in the `controllers` directory
//This way `Loader class will find it.
export default class HomeController {
constructor() {
this.title = 'Home Controller';
}
}
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
export default class Loader {
/**
* Loader controller
*
* Requires `app` as string application name.
* Allows to provide custom structure map.
*
* @param app
* @param structure
*/
constructor(app, structure) {
const bulk = require('bulk-require');
this.module = angular.module(app);
this.structure = structure || {
constant: bulk(__dirname, ['./constants/**/!(*.spec).js']),
config: bulk(__dirname, ['./config/**/!(*.spec).js']),
controller: bulk(__dirname, ['./controllers/**/!(*.spec).js']),
service: bulk(__dirname, ['./services/**/!(*.spec).js']),
provider: bulk(__dirname, ['./providers/**/!(*.spec).js']),
factory: bulk(__dirname, ['./factories/**/!(*.spec).js']),
component: bulk(__dirname, ['./components/**/!(*.spec).js']),
directive: bulk(__dirname, ['./directives/**/!(*.spec).js']),
filter: bulk(__dirname, ['./filters/**/!(*.spec).js'])
};
Object.defineProperty(Function.prototype, 'name', {
get: function () {
return /function ([^(]*)/.exec(this + "")[1];
}
});
this.register();
}
/**
* Register app modules from structure map
*/
register() {
let self = this;
angular.forEach(self.structure, function (value, key) {
self.declare(key, value);
});
}
/**
* Register app modules by structure key
*
* @param name
* @param map
*/
declare(name, map) {
let self = this;
Object.keys(map).forEach((key) => {
let item = map[key];
if (!item) {
return;
}
if (item && typeof item === 'function') {
self[name](item);
} else {
self.declare(name, item);
}
});
}
/**
* Register constants
*
* @param item
* @returns {Loader}
*/
constant(item) {
let constructorFn = this.normalizeConstructor(item);
this.module.constant(constructorFn.name, new constructorFn());
return this;
}
/**
* Add config
*
* @param item
* @returns {Loader}
*/
config(item) {
let constructorFn = this.normalizeConstructor(item);
this.module.config(constructorFn);
return this;
}
/**
* Register controller
*
* @param item
* @returns {Loader}
*/
controller(item) {
let constructorFn = this.normalizeConstructor(item);
this.module.controller(constructorFn.name, constructorFn);
return this;
}
/**
* Register component
*
* @param item
* @returns {Loader}
*/
component(item) {
let constructorFn = this.normalizeConstructor(item);
this.module.component(constructorFn.name, new constructorFn());
return this;
}
/**
* Register service
*
* @param item
* @returns {Loader}
*/
service(item) {
let constructorFn = this.normalizeConstructor(item);
this.module.service(constructorFn.name, constructorFn);
return this;
}
/**
* Register provider
* @param item
* @returns {Loader}
*/
provider(item) {
let constructorFn = this.normalizeConstructor(item);
this.module.provider(constructorFn.name, constructorFn);
return this;
}
/**
* Register factory
*
* There are two possible way to implement factories.
* `module.factory()` method is specifically for when you are not using classes.
* The `module.service()` method was specifically designed for when you want to define your services as classes (or instantiable types).
* So there is actually no point in trying to hack together a way to register a class via the `module.factory()` method.
* Just use `module.service()` instead.
*
* @param item
* @returns {Loader}
*/
factory(item) {
let constructorFn = this.normalizeConstructor(item);
if (constructorFn.factory) {
this.module.service(constructorFn.name, constructorFn.factory);
} else {
this.module.factory(constructorFn.name, this.createFactoryArray(constructorFn));
}
return this;
}
/**
* Register directive
*
* @param item
* @returns {Loader}
*/
directive(item) {
let constructorFn = this.normalizeConstructor(item);
if (!constructorFn.prototype.compile) {
constructorFn.prototype.compile = () => {
};
}
let originalCompileFn = this.cloneFunction(constructorFn.prototype.compile);
this.override(constructorFn.prototype, 'compile', function () {
return function () {
originalCompileFn.apply(this, arguments);
if (constructorFn.prototype.link) {
return constructorFn.prototype.link.bind(this);
}
};
});
this.module.directive(constructorFn.name, this.createFactoryArray(constructorFn));
return this;
}
/**
* Register filter
*
* @param item
* @returns {Loader}
*/
filter(item) {
let constructorFn = this.normalizeConstructor(item);
this.module.filter(constructorFn.name, constructorFn);
return this;
}
/**
* Clone a function
* @param original
* @returns {Function}
*/
cloneFunction(original) {
return function () {
return original.apply(this, arguments);
};
}
/**
* Convert a constructor function into a factory function which returns a new instance of that
* constructor, with the correct dependencies automatically injected as arguments.
*
* In order to inject the dependencies, they must be attached to the constructor function with the
* `$inject` property annotation.
*
* @param constructorFn
* @returns {Array.<T>}
* @private
*/
createFactoryArray(constructorFn) {
var args = constructorFn.$inject || [];
var factoryArray = args.slice();
factoryArray.push((...args) => {
var instance = new constructorFn(...args);
for (var key in instance) {
if (instance.hasOwnProperty(key)) {
instance[key] = instance[key];
}
}
return instance;
});
return factoryArray;
}
/**
* If the constructorFn is an array of type ['dep1', 'dep2', ..., constructor() {}]
* we need to pull out the array of dependencies and add it as an $inject property of the
* actual constructor function.
*
* @param input
* @returns {*}
* @private
*/
normalizeConstructor(input) {
var constructorFn;
if (input.constructor === Array) {
var injected = input.slice(0, input.length - 1);
constructorFn = input[input.length - 1];
constructorFn.$inject = injected;
} else {
constructorFn = input;
}
return constructorFn;
}
/**
* Override an object's method with a new one specified by `callback`.
*
* @param object
* @param methodName
* @param callback
*/
override(object, methodName, callback) {
object[methodName] = callback(object[methodName])
}
}
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
import angular from 'angular';
import loader from './loader';
import 'angular-ui-router';
const app = 'app';
const requires = [
'ui.router',
];
window.app = angular.module(app, requires);
const register = new loader(app);
angular.bootstrap(document, [app], {
strictDi: true
});
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
//Location in the `config` directory
//This way `Loader class will find it.
export default function routerConfig($stateProvider, $locationProvider, $urlRouterProvider) {
'ngInject';
$urlRouterProvider.otherwise('/');
$locationProvider.html5Mode(true);
$stateProvider
.state('Home', {
url: '/',
controller: 'HomeController as home',
templateUrl: 'home.html',
title: 'Home'
});
}
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
//Location in the `providers` directory
//This way `Loader class will find it.
export default class ThingProvider {
constructor() {
this.settings = {
storage: 'sessionStorage', //localStorage
storageKey: 'linkedInConfig'
};
}
config(settings) {
for (var attr in settings) {
if (settings.hasOwnProperty(attr)) {
this.settings[attr] = settings[attr];
}
}
let state = this.getState();
if (!state) {
this.setState(this.settings.state)
} else {
this.settings.state = state;
}
}
setState(data) {
window[this.settings.storage].setItem(this.settings.storageKey + '-state', JSON.stringify(data));
}
getState() {
var data = window[this.settings.storage].getItem(this.settings.storageKey + '-state');
return (data) ? JSON.parse(data) : false;
}
$get() {
return {
getState: this.getState.bind(this)
};
}
/**
* (c) Rafał Lorenz <vardius@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
export default class UserService {
constructor($http) {
'ngInject';
this.$http = $http;
}
getFullName() {
return this.$http.get('api/user/details');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment