使用“Coffee Script Class”而不是Method作为Angular JS ng-controller

时间:2013-01-11 12:13:48

标签: class controller coffeescript angularjs

我想做一些我认为使用“Coffee Script Class”和Angular JS结构的好方法。

<!doctype html>
<html ng-app>

  <head>
    <meta charset=utf-8>
    <meta name=viewport content="width=device-width, initial-scale=1">
    <title>Main Test</title>
    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <link href="bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
    <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="js/angular.min.js"></script>
    <script type="text/javascript" src="js/coffee.js"></script>
  </head>

  <body>
    <div ng-controller="MainClass" style="margin-left:10px">
      <h2>All todos: {{test()}}</h2>
    </div>
  </body>

</html>

请注意,我将DIV ng-controller设置为主要类,并在H2 HTML标记内设置绑定test()方法。

class AngularJSController
  constructor: ($scope, $main) ->

    $scope.test = MainClass.prototype.test
    MainClass.test = MainClass.prototype.test
    $main.test = MainClass.prototype.test
    test = MainClass.prototype.test
    @test = MainClass.prototype.test

    console.log @test

class MainClass extends AngularJSController
  constructor: ($scope) ->
    super $scope, this

    setTimeout (->
        console.log test()
      ), 1000

    test();

  test: -> 'aloha!'

在AngularJSController构造函数中,我尝试了所有我希望在MainClass范围内设置我的超类方法TEST的表单,但没有成功。

我正在尝试这样做,因为我想在Angular JS控制器和组件上使用类。

我已经陷入的问题:

  1. 如果我尝试在setTimeout中使用@test()而不是test(),jQuery已经用一种JQuery窗口对象替换了this属性。

    setTimeout (-> console.log @test()), 1000
    
  2. 我不知道test()调用的范围究竟是什么,如果这个地方(或@导致咖啡)不同于任何地方。

    test() != this.test() != @.test() # the first scope isn't the same scope of last two calls
    

6 个答案:

答案 0 :(得分:8)

我使用了以下语法:

app = angular.module 'myapp', []

class MySimpleCtrl

  @$inject: ['$scope'] 
  constructor: (@scope) ->
    @scope.demo = 'demo value'
    @scope.clearText = @clearText

  clearText: =>
    @scope.demo = ""

app.controller 'MySimpleCtrl', MySimpleCtrl

angular.bootstrap document, ['myapp']

看看这个jsFiddle:      http://jsfiddle.net/jwcMA/

答案 1 :(得分:4)

这是一个基类的通用方法:

http://www.devign.me/angular-dot-js-coffeescript-controller-base-class/

<强> BaseCtrl.coffee

# dependency - Function.prototype.bind or underscore/lodash

app = angular.module 'someApp'

class @BaseCtrl
  @register: (app, name) ->
    name ?= @name || @toString().match(/function\s*(.*?)\(/)?[1]
    app.controller name, @

  @inject: (args...) ->
    @$inject = args

  constructor: (args...) ->
    for key, index in @constructor.$inject
      @[key] = args[index]

    for key, fn of @constructor.prototype
      continue unless typeof fn is 'function'
      continue if key in ['constructor', 'initialize'] or key[0] is '_'
      @$scope[key] = fn.bind?(@) || _.bind(fn, @)

    @initialize?()

<强> BookFormCtrl.coffee

app = angular.module 'someApp'

class BookFormCtrl extends BaseCtrl
  @register app
  # list of dependencies to be injected
  # each will be glued to the instance of the controller as a property
  # e.g. @$scope, @Book
  @inject '$scope', 'Book'

  # initialize the controller
  initialize: ->
    @$scope.book =
      title: "Hello"

  # automatically glued to the scope, with the controller instance as the context/this
  # so usable as <form ng-submit="submit()">
  # methods that start with an underscore are considered as private and won't be glued
  submit: ->
    @Book.post(@$scope.book).then =>
      @$scope.book.title = ""

答案 2 :(得分:0)

  1. setTimeout与jQuery没有任何关系,但传递给setTimeout的函数确实在全局(窗口)上下文中执行。使用胖箭头将其显式绑定到当前范围。 http://coffeescript.org/#fat_arrow

    setTimeout (=>
      console.log @test()
    ), 1000
    
  2. 抱歉,我不确定你在问什么。

答案 3 :(得分:0)

Angular确实支持Coffeescript类!在大多数情况下。 我发现使用RequireJs时遇到问题,期待一个函数而不是一个对象。

看看这里: http://softwareninjaneer.com/blog/writing-angularjs-controllers-coffeescript-classes/

答案 4 :(得分:0)

我对@ malix的答案没有运气,尽管它确实引导我找到了一个有效的解决方案。这就是我在做的事情:

'use strict'

class ImportsCtrl
  constructor: ($scope, Import) ->
    Import.query().then (imports) -> $scope.imports = imports

angular.module("greatDealsApp").controller "ImportsCtrl", ImportsCtrl

这是一个将$scope转换为ImportsCtrl属性的人为举例:

'use strict'

class ImportsCtrl
  constructor: ($scope, Import) ->
    @scope = $scope
    @Import = Import
    @loadImports()

  loadImports: =>
    @Import.query().then (imports) => @scope.imports = imports

angular.module("greatDealsApp").controller "ImportsCtrl", ImportsCtrl

我不确定这是否重要,但我正在使用ng-annotate

答案 5 :(得分:-1)

这是不可能的。您不能将控制器设置为对象(MainClass),因为AngularJS确保控制器是一个函数。

您需要自定义AngularJS才能执行此操作。我认为这不是一个好主意。

参考