carylandholt / ng-classify Goto Github PK
View Code? Open in Web Editor NEWConvert CoffeeScript classes to AngularJS modules
License: MIT License
Convert CoffeeScript classes to AngularJS modules
License: MIT License
When using resolve for ex with the "messages" var.. throws DI error.. because its loaded in the array as a dependency.. but its not.
Is there a way of avoiding this?
Thanks!
ex:
resolve:
lives: (LiveService) ->
LiveService.getAll()
class Home extends Controller
constructor: ($scope, $state, Faye, authenticationService, lives)
turns into
['$scope', '$state', 'Faye', 'authenticationService', 'lives' ...]
I am sure this is a simple issue, but confusing nonetheless. I have an angular factory that I am trying to "ng-classify". The existing code looks something like this:
app.factory 'Data', [
'$log'
"$q'
($log, $q) ->
getData1: ->
data1 = $q.defer()
. . .
return data1.promise
getData2: ->
data2 = $q.defer()
. . .
return data2.promise
getSomeComboData: ->
comboData = $q.defer()
$q.all(@getData1, @getData2).then (Data1, Data2) ->
. . .
return ComboData.promise
. . .
]
This works. No problem. Sometimes my controllers need Data1, sometimes Data2, sometimes ComboData. I can imagine other scenarios where a factory method might need to call another public method of the same factory.
This is what I did to "ng-classify" it:
class Data extends Factory
constructor: ($log, $q) ->
return: {
getData1: ->
data1 = $q.defer()
. . .
return data1.promise
getData2: ->
data2 = $q.defer()
. . .
return data2.promise
getSomeComboData: ->
comboData = $q.defer()
$q.all(@getData1, @getData2).then (Data1, Data2) ->
. . .
return ComboData.promise
. . .
}
The problem is now @getdata1 and @getdata2 are undefined. Somehow the "this" reference to the factory singleton has been lost. Am I missing something?
It would be very useful to us to be able to add new methods, etc to controllers (and perhaps services/factories) that are being registered with angular.
I propose changing this lib the property DI style: MyController.$inject = ['$scope', 'greeter'];
so that this can also be transformed, then provide an option to transform all classes:
controller:
format: 'camelCase'
suffix: 'Controller'
transform: (className, obj) -> obj
i realize that this would mean that this same transform function would have to be included in all the boiler plate code output by ng-classify - this kind of sucks, but maybe I can just attach that transform function on to window.angular or find some other optimization. Even without the optimization, I think this provides us with a great way to solve some cross cutting issues at a small cost of file size
Hi Cary,
class Greetings extends Provider
generates:
angular.module('app').provider('greetingsProvider', ['$log', function Greetings ($log) {
I think it should generate:
angular.module('app').provider('greetings', ['$log', function Greetings ($log) {
So that I dont have to configure it with
angular.module('app').config (gretingsProviderProvider) ->
Usually, providers are used to generate configurable services, so we may want to actually generate
angular.module('app').provider('greetingsService', ['$log', function Greetings ($log) {
Finally I understand how to use ng-classify and it's great. I create with success some controller and some services, but I still have some issue with the Factory.
I try to convert this Factory in coffeescript with ng-classify
angular.module('myApp.services', ['myApp.config'])
// DB wrapper
.factory('DB', function($q, DB_CONFIG) {
var self = this;
self.db = null;
self.init = function() {
// Use self.db = window.sqlitePlugin.openDatabase({name: DB_CONFIG.name}); in production
self.db = window.openDatabase(DB_CONFIG.name, '1.0', 'database', -1);
angular.forEach(DB_CONFIG.tables, function(table) {
var columns = [];
angular.forEach(table.columns, function(column) {
columns.push(column.name + ' ' + column.type);
});
var query = 'CREATE TABLE IF NOT EXISTS ' + table.name + ' (' + columns.join(',') + ')';
self.query(query);
console.log('Table ' + table.name + ' initialized');
});
};
self.query = function(query, bindings) {
bindings = typeof bindings !== 'undefined' ? bindings : [];
var deferred = $q.defer();
self.db.transaction(function(transaction) {
transaction.executeSql(query, bindings, function(transaction, result) {
deferred.resolve(result);
}, function(transaction, error) {
deferred.reject(error);
});
});
return deferred.promise;
};
self.fetchAll = function(result) {
var output = [];
for (var i = 0; i < result.rows.length; i++) {
output.push(result.rows.item(i));
}
return output;
};
self.fetch = function(result) {
return result.rows.item(0);
};
return self;
})
My Factory is:
class DatabaseFactory extends Factory
constructor: ($q, DBCONFIG) ->
return {
init: () ->
@db = window.openDatabase(DBCONFIG.name, "1.0", "database", -1)
angular.forEach DBCONFIG.tables, (table) ->
columns = []
angular.forEach table.columns, (column) ->
columns.push column.name + " " + column.type
return
execute_query = "CREATE TABLE IF NOT EXISTS " + table.name + " (" + columns.join(",") + ")"
query(execute_query)
console.log "Table " + table.name + " initialized"
return
query: (query, bindings) ->
bindings = (if typeof bindings isnt "undefined" then bindings else [])
deferred = $q.defer()
@db.transaction (transaction) ->
transaction.executeSql query, bindings, ((transaction, result) ->
deferred.resolve result
return
), (transaction, error) ->
deferred.reject error
return
return
deferred.promise
fetchAll: (result) ->
output = []
i = 0
while i < result.rows.length
output.push result.rows.item(i)
i++
output
fetch: (result) ->
result.rows.item 0
}
It doesn't work: `Uncaught ReferenceError: query is not defined``
If I use a service everything works but I cannot understand why I can't call query from init.
TypeError: Cannot call method 'forEach' of undefined
class Home extends Controller
constructor: do ->
I cannot understand how to use the api.
For example: now the Setting controller becomes "settingController". I want to change it to "SettingCrtl"
I see the options, but I don't understand how I can override the default behaviour!
Roberto
hi, the code compiled by ng-classify in atom editor is in another panel, i can't copy it.
is there any solution ?
thanks !
I'm currently creating an Angular app in CoffeeScript and I use Browserify for module loading, the problem is that it doesn't work with ng-classify, so I thought that this could be possible:
before:
module.export = class Admin extends Controller
constructor: ($scope) ->
ng-classified:
class Admin
constructor: ($scope) ->
module.export = angular.module('app').controller 'adminController', ['$scope', Admin]
Hi,
As angular 1.5 have been released, there is also the option to start using components instead of directives. https://docs.angularjs.org/guide/component
Would be cool to implement it on ng classify :)
The following:
class App extends App
constructor: ->
return []
results in:
var App;
App = (function() {
function App() {
return [];
}
return App;
})();
angular.module('app', App());
Because App
is a constructor function and begins with a capital letter, JSHint expects it to be called with the new
keyword.
The following is the expected, JSHint-friendly, output:
var App;
App = (function() {
function App() {
return [];
}
return App;
})();
angular.module('app', new App());
See http://jshint.com/docs/options/#newcap
Thanks @chasm
Hi,
It looks like ng-classify breaks with the latest version of angular. I think that it's a error related to the nature of coffee-script.
With the new Angular, for example a directive returns the last function in the Directive
class Some extends Directive
constructor: ->
return {
controller: ($scope) ->
$scope.someFunction = ->
}
That will return the function $scope.someFunction and not the whole directive for some reason. But if returning the directive at the end then it works
class Some extends Directive
constructor: ->
return {
controller: ($scope) ->
$scope.someFunction = ->
return
}
Hi,
I have been trying this and looks amazing, thanks.
I have a problem when using it for "RUN"
Here is the code that breaks:
class onLoad extends Run
constructor: ->
@ey()
ey: =>
console.log 'working'
this(@) refers to Window by the way using this syntax
you have
provider:
format: 'camelCase'
suffix: 'Provider'
So if I create a provider like this class Foo extends Provider
ng-classify will register it as fooProvider
, but angular will register it as fooProviderProvider
because it also appends Provider
to provider names!
You can try this yourself, create a provider with default settings and try to inject it as fooProvider
- it will not be found.
Currently only regualr coffee seems to be supported.
I'm trying to "classify" an existing angular factory, and I am not sure I understand what this is telling me. This is how it was originally written in coffeescript:
'use strict';
angular.module('App')
.factory 'Data', [
'$log'
'$q'
($log, $q) ->
openDB : ->
db = new PouchDB 'myDB'
return db
getDB: ->
db = $q.defer()
db = @openDB()
db.allDocs {include_docs: true}, (err, res) ->
if err
$log.log err
db.resolve err
else
db.resolve res.rows
return db.promise
#[and so on]
It goes on in the same vein with all the usual CRUD functions like findRecord, addRecord, etc. It works fine, but I wanted to "classify" this code to better encapsulate it for future reuse.
this is how I rewrote it:
class Data extends Factory
constructor: ($log, $q) ->
openDB : ->
db = new PouchDB 'myDB'
return db
getDB: ->
db = $q.defer()
db = @openDB()
db.allDocs {include_docs: true}, (err, res) ->
if err
$log.log err
db.resolve err
else
db.resolve res.rows
return db.promise
#[and so on]
However, I am getting the following error:
Provider 'Data' must return a value from $get factory method.
I'm not sure I understand what is going wrong, and the examples in the API reference do not show a factory with more than one method. Can you help me understand how the classify utility would handle this?
HttpStatusCodes should result in HTTP_STATUS_CODES
camelToDash = (str) ->
str.replace(/([a-z\d])([A-Z])/g, '$1_$2').toUpperCase()
Hi There,
So I've been having trouble when trying to run my app after compilation.
At the moment I'm keeping all my coffee classes in separate files then using gulp to ngClassify() then concat all the files together which compiles to the following script:
var App;
App = (function() {
function App() {
return ['firebase', 'ngRoute'];
}
return App;
})();
angular.module('app', new App());
var Routes;
Routes = (function() {
function Routes($locationProvider, $routeProvider) {
$locationProvider.html5Mode(true);
$routeProvider.when('/', {
templateUrl: 'views/home.html',
controller: 'homeController'
}).when('/project/:id', {
templateUrl: 'views/project.html',
controller: 'projectController'
}).otherwise({
templateUrl: 'views/404.html'
});
}
return Routes;
})();
angular.module('app').config(['$locationProvider', '$routeProvider', Routes]);
var Home;
Home = (function() {
function Home($scope) {
$scope.controller = this;
}
return Home;
})();
angular.module('app').controller('homeController', ['$scope', Home]);
var Project;
Project = (function() {
function Project($scope, $routeParams, $firebaseObject) {
var ref, url;
$scope.controller = this;
url = 'https://scorching-fire-8072.firebaseio.com/projects/' + $routeParams.id;
ref = new Firebase(url);
$scope.data = $firebaseObject(ref);
}
return Project;
})();
angular.module('app').controller('projectController', ['$scope', '$routeParams', '$firebaseObject', Project]);
This looks all good to me but maybe I'm missing something silly here?
Hope you can help!
Thanks,
Scott.
Hi,
One thing that I miss from other projects (no-angular) is the possibility to create others functions that are siblings of the constructor. Right now I put everything inside the constructor.
It kinds of works with controllers if I define every dependency again (@scope = $scope), but inside functions that have a return inside (directives) it's impossible to do.
Do you know any clean way to do it? It would improve the quality for the code a lot and I have not seen it in any angular project yet, ever. I know it has probably anything to do with ng-classify but it's the closest approach in that direction.
Hi,
thanks for your excelent work, but I can not figure out how to use it with UI-Router
class Home extends controller
###
The constructor
###
constructor: (userService) ->
My application is split into multiple modules. Is it possible to specify the module name ?
your demo site is down on cloud 9
I would like bower support, so I can more easily use this with rails (https://rails-assets.org) - the rails gem is out of date, and even if it is updated, it will most likely not be updated in the future. This makes rails-usage much easy.
I made a pull request for this, you can accept it to allow
bower install ng-classify
or in rails:
source 'https://rails-assets.org' do
gem 'rails-assets-ng-classify', '~> X.X'
end
Thanks!
class A extends Controller
constructor: (aa, ab) ->
return class AA extends Service
constructor: (aaa) ->
console.log 'perms'
I have a quick question about ng-classify. Let's take this Service
class Item extends Service
constructor: ->
@items = [
{id: 1, label: 'Item 0'}
{id: 2, label: 'Item 1'}
]
@list = ->
@items
@add = (item) ->
@items.push item
I cannot understand why everything is inside the constructor...
Is this wrong?
class Item extends Service
constructor: ->
@items = [
{id: 1, label: 'Item 0'}
{id: 2, label: 'Item 1'}
]
@list()
@add(item)
list = ->
@items
add = (item) ->
@items.push item
Hi, Cary
We are looking at using ng-classify in buildbot, but we are not very happy about the filePath based approach
what about something with a syntax like:
class Home extends buildbot.common.Controller
constructor: ($log) ->
$log.info 'homeController instantiated'
or:
class Home extends Controller("buildbot.common")
constructor: ($log) ->
$log.info 'homeController instantiated'
which are both "valid" coffee syntax
I wish to be able to add more than one module using ng-classify, so i will be able to follow angular guidelines (https://docs.google.com/document/d/1XXMvReO8-Awi1EZXAXS4PzDzdNvV6pGcuaF4Q9821Es/pub).
Is it possible just now?
Thank you, I really love your work.
ng-classify should use APP_NAME as it's appName
option so that the app works :)
If that sounds right, I'd be happy to submit a PR
After redirecting it 404s.
https://preview.c9users.io/carylandholt/ng-classify-browserify/index.html
Hi,
It's been a year and half since I had the chance to use ng-classify and coffeescript... I seem to be having an issue and can't figure it out.
this is my ng-classify code
# create module
class App extends App('common')
constructor: ->
return []
# create provider
class commonConfig extends Provider('common')
constructor: ->
@config = {}
@$get = ->
{ config: @config }
# create the factory 'common'
class common extends Factory('common')
constructor: ($q, $rootScope, $timeout, commonConfig, logger) ->
service =
$broadcast: $broadcast
$q: $q
$timeout: $timeout
logger: logger
activateController: activateController
# passthrough of the angular $broadcast service
$broadcast = ->
$rootScope.$broadcast.apply $rootScope, arguments
# global function used to activate a controller once all promises have completed
activateController = (promises, controllerId) ->
$q.all(promises).then (eventArgs) ->
data = controllerId: controllerId
$broadcast commonConfig.config.controllerActivateSuccessfulEvent, data
# hide the workingOnIt animation
#$broadcast commonConfig.config.workingOnItToggleEvent, { show: false }
return service
which consistently throws a provider issue of commonConfigProvider. yet when I use plain js it works
(function () {
'use strict';
// create module
angular.module('common', [])
// create provider
.provider('commonConfig', function () {
this.config = {};
this.$get = function () {
return {
config: this.config
};
};
})
// create the factory 'common'
.factory('common', ['$q', '$rootScope', '$timeout', 'commonConfig', 'logger', common]);
// function factory 'common'
function common($q, $rootScope, $timeout, commonConfig, logger) {
var service = {
// passthough common angular dependencies
$broadcast: $broadcast,
$q: $q,
$timeout: $timeout,
// my services
logger: logger,
activateController: activateController
};
return service;
// passthrough of the angular $broadcast service
function $broadcast() {
return $rootScope.$broadcast.apply($rootScope, arguments);
}
// global function used to activate a controller once all promises have completed
function activateController(promises, controllerId) {
return $q.all(promises).then(function(eventArgs) {
var data = { controllerId: controllerId };
$broadcast(commonConfig.config.controllerActivateSuccessfulEvent, data);
// hide the workingOnIt animation
//$broadcast(commonConfig.config.workingOnItToggleEvent, { show: false });
});
}
}
})();
am I missing something? I've spent hours troubleshooting this :(
Hi Cary,
Do you have any method, on how you would do test coverage with karma and ng-classify?
I can get coverage with the compiled js, and I'm trying to do the same with the coffee script file directly, to get a nice report, with annotated coffeescript files, but I miss the karma-ng-classify-preprocessor...
It would be good if this tool had a CLI. I can write one and PR it, the only thing that id like feedback on is how you would like the options to translate into arguments. Im thinking something like
./ngclassify --controller-format=camel --controller-suffix=Poop --value-format=none app-name=my.app ./input.coffee ./output.js
I have my own base classes for Controller, Service etc.
How can I preserve them ?
~ DELETED ~
Estou encontrando os problemas descritos em: http://pt.stackoverflow.com/questions/56023/filter-com-angularjs-e-gulp
Anything other than the following two patterns should return the original content.
class {{appName}} extends {{App|Animation|Config|Controller|Directive|Factory|Filter|Provider|Run|Service}}
constructor: ({{params}}) ->
# module body here
class {{name}} extends {{App|Constant|Value}}
@constructor = {{value}}
Currently an exception is thrown.
I put example controller to check how it works and have been suprised. It was angular error
class Projects extends Controller
constructor: ($scope) ->
$scope.init ->
console.log 'Hello World!'
Uncaught Error: [$injector:nomod] Module 'todo_list' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.3.0-build.3042+sha.76e57a7/$injector/nomod?p0=todo_list
It happen because module was without dependency
angular.module('todo_list').controller('ProjectsCtrl', ['$scope', Projects]);
It requires to create App module with it and not truly documented on usage section
https://github.com/CaryLandholt/ng-classify#coffeescript
It works!
class App extends App
constructor: ->
return []
class Projects extends Controller
constructor: ($scope) ->
$scope.init ->
console.log 'Hello World!'
Oh, I've checked down. This section also does not work
https://github.com/CaryLandholt/ng-classify#multiple-apps
class Home extends Controller('common')
constructor: ($log) ->
$log.info 'homeController instantiated'
Uncaught Error: [$injector:nomod] Module 'common' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.3.0-build.3042+sha.76e57a7/$injector/nomod?p0=common
Great concept!
I installed ng-classify with npm but I am unclear how to use it. How does it get recognized by the CoffeeScript compiler?
Great module, I like the idea of less code. One question though, is there the ability to chain?
Say I have this:
angular.module( 'sailng.users', [])
.config( ['$stateProvider',function config( $stateProvider ) {
$stateProvider.state( 'users', {
url: '/users',
views: {
"main": {
controller: 'UserCtrl',
templateUrl: 'users/index.tpl.html'
}
},
data:{ pageTitle: 'User' }
});
}])
.controller( 'UserCtrl',['$scope', '$sails', 'lodash', 'config', 'titleService', 'UserModel','$filter', 'ngTableParams', function UserController( $scope, $sails, lodash, config, titleService, UserModel,$filter, ngTableParams ) {
...
}]);
is it possible to chain .module().config().controller() with this module?
Thanks
i have this error
https://docs.angularjs.org/error/$injector/nomod?p0=app
with just this code when i open my test webpage
class Admin extends Controller
constructor: ($scope, someService) ->
$scope.coolMethod = someService.coolMethod()
cube = (x) ->
x * x * x
class Home extends Controller
constructor: ($log) ->
$log.info 'homeController instantiated'
$log.info cube(3)
The docs read ngClassify(coffeeScriptClass, options)
Should read ngClassify(content, options)
moduleType not being replaced properly
class Home extends Ng.Controller
console.log 'here'
ngClassify(content, prefix: 'Ng')
TypeError: Cannot call method 'split' of undefined
Hi,
After changing almost everything to classify I found that the most difficult part was using Factories.
I ended up using the same syntax as directives. It's the best way to do it?
class test extends Factory
constructor: ($http, $q, $location) ->
return {
search: (query) ->
# console.log 'search...', query
}
Thank you for ng-classify, really useful
extends a controller or a service for exemple, will generate only one module name
but in my case i am working on multiple modules, and it will be useful if you develop the
configuration/options side, so then we can define a prefix for every module name
best regards.
App.controller => angular.module('app')
Dashboard.controller => angular.module('dashboard')
I am interested in your take on how to use this tool with a mixin provider to allow me to have a BaseController
that also uses ng-classify. I tried having the base controller extend Controller
and concrete controllers extend the base, but that does not work.
The next thought is to use a mixin to augment the the classes that extend Controller
.
I think that this is a common use-case with using this tool and I would be interested to know what your take on an implementation would be
This can help avoid potential class collisions
class Home extends Ng.Controller
constructor: ->
console.log 'homeController instantiated'
options.prefix = 'Ng'
or options.prefix = 'Ng.'
or options.prefix = 'Ng.My'
If I wrap this code
class Admin extends Controller('app.controllers')
constructor: ($scope, someService) ->
$scope.coolMethod = someService.coolMethod()
in requirejs
define( ->
class Admin extends Controller('app.controllers')
constructor: ($scope, someService) ->
$scope.coolMethod = someService.coolMethod()
)
compiler will generate smth like this:
define(function() {
var Admin;
return Admin = (function(_super) {
__extends(Admin, _super);
function Admin($scope, someService) {
$scope.coolMethod = someService.coolMethod();
}
return Admin;
})(Controller('app.controllers'));
});
Is it possible to generate the same code as before implementing requirejs but in it's wrapper?
I have this Factory:
.factory('ItemService', [function() {
var items = [
{id: 1, label: 'Item 0'},
{id: 2, label: 'Item 1'}
];
return {
list: function() {
return items;
},
add: function(item) {
items.push(item);
}
};
I try in this way but it doesn't work.
class ItemService extends Factory
constructor: ->
return {
items: [
{id: 1, label: 'Item 0'},
{id: 2, label: 'Item 1'}
]
list: () ->
@items
add: (item) ->
@items.push(item)
}
My controller is
class Main extends Controller
constructor: ->
@tab = 'first'
@open = (tab) =>
@tab = tag
class Sub extends Controller
constructor: (ItemService) ->
@list = () =>
return ItemService.list
@add = () =>
console.log('pippo')
Can you help me?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.