majgis/ngify

Add support for loading POJO's

majgis opened this issue · 5 comments

Wouldn't it be nice if we could skip the angular boilerplate and just write plain old JavaScript objects (POJOs)?

The following file naming convention for loading angular.module convenience methods will be used:

<name>.<method>.js

The following examples show the require statement and the associated angular statement it is converted into:

    //Provider
    require("./example.provider.js")
    angular.module('ngify').provider('example', [ "injectMe", require("./example.provider.js") ] )  

    //Factory
    require("./example.factory.js")
    angular.module('ngify').factory('example', [ "injectMe", require("./example.factory.js) ] )

    //Service
    require("./example.service.js")
    angular.module('ngify').service('example', [ "injectMe", require("./example.service.js) ] )

    //Value
    require("./example.value.js")
    angular.module('ngify').value('example', require("./example.value.js))

    //Constant
    require("./example.constant.js")
    angular.module('ngify').constant('example', require("./example.constant.js))

    //Animation
    require("./example.animation.js")
    angular.module('ngify').animation('example',  [ "injectMe", require("./example.animation.js) ] )

    //Filter
    require("./example.filter.js")
    angular.module('ngify').filter('example',  [ "injectMe", require("./example.filter.js) ] )

    //Controller
    require("./example.controller.js")
    angular.module('ngify').controller('example',  [ "injectMe", require("./example.controller.js) ] )

    //Directive
    require("./example.directive.js")
    angular.module('ngify').directive('example',  [ "injectMe", require("./example.directive.js) ] )

    ////For these last two, the name is optional and is not used if given

    //Config
    require("./example.config.js")
    angular.module('ngify').config( [ "injectMe", require("./example.config.js) ] )

    //Run
    require("./example.run.js")
    angular.module('ngify').run( [ "injectMe", require("./example.run.js) ] )

In each of the cases with injector minification syntax, the injectables (in these examples just "injectMe") will be taken from the signature of the function returned by the require statement.

The functionality for templates will remain the same.

@davisarchibald, how do you like this approach?

tl,dr: Adding all angular.module convenience methods based on file name, behaves as expected from Angular boilerplate.

Yes! This is great, allows your file names to reflect their purpose as well as removes the hard coded Angular convenience method in the file. Hopefully making the files more likely to be framework agnostic.

The more I think about it, the more I dislike relying on metadata in the file name.

How about the following:

  1. Every file ending in .js will be processed and registered with Angular injector if it has @ng annotation
  2. Yes the @ng annotation syntax is not as terse, but it is the most flexible and handles all corner cases, for example when a service has a name that isn't valid as a function parameter.
  3. If we still want some convenience shorthands, we can add them after this core functionality is finished.

Examples:

A service

function MySweetClass(abc123) {

}

exports = module.exports = MyClass;

exports['@ng'] ={
    "type": "service",
    "inject": [ "abc123" ],
    "name": "myClass"
}

A factory

function MyFactory(xyz){
  return xyz('frank');
}

exports = module.exports = MyFactory;

exports['@ng'] = {
    "type": "factory",
    "inject": ["xyz"],
    "name": "xyzFrank"
}

A value

var myObject = {};

exports = module.exports = myObject;

exports['@ng'] = {
    "type": value,
    "name": "myObject"
}

Also, the require statement won't be messed with. The angular boilerplate will be appended to the end of a file containing the @ng annotation

Issue resoved in 72ca812