Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating Angular Controller from Fay Module: API brainstorm #3

Open
chreekat opened this issue Oct 14, 2013 · 5 comments
Open

Creating Angular Controller from Fay Module: API brainstorm #3

chreekat opened this issue Oct 14, 2013 · 5 comments

Comments

@chreekat
Copy link

Here's what I'm using to generically build a controller out of a Fay module.

# CoffeeScript

angModule = angular.module("angModule", [])

angModule.controller("FooCtl", ($scope) ->
        $scope[k] = v for own k, v of Strict.HaskModule
)

Assuming this is even a good starting point, is there a way to package up that code into Fay action? Say, for instance,

angularModule :: Text -- ^ module's name
              -> [AngularModule] -- ^ module deps
              -> Fay AngularModule

addController :: Text -- ^ controller name
              -> Text -- ^ Haskell module to use (FIXME, obviously(?))
              -> AngularModule -- ^ Angular module to attach the controller to
              -> Fay ()

and then:

main = do
    angMod <- angularModule "angModule"
    addController "FooCtl" "HaskModule" angMod
@chreekat
Copy link
Author

I think this is a dead end; no sense in trying to treat modules as first class just yet.

@bergmark
Copy link
Member

I think we can reopen this, even if the module approach isn't appropriate people may have ideas on how to do it better.

I don't know much about angular controllers, so I'm just brainstorming a bit too.

I think you can accomplish the same task by using records,
data MyController = MyController { doFoo :: Fay (), doBar :: Double -> Double, qux :: Text } will serialize to an object where these properties can be used as you'd expect from js.

You probably also want some generic notion of Controller, which you can do like this:

class Controller
instance Controller MyController

addController :: Controller c => Text -> Automatic c -> AngularModule -> Fay ()

Note that Automatic is needed since c is a type variable and wouldn't be serialized otherwise.

This depends a bit on how angular controllers work, can they define arbitrary methods? Are some required?

@bergmark bergmark reopened this Oct 14, 2013
@kfish
Copy link
Member

kfish commented Oct 15, 2013

Controllers can define arbitrary methods, but by default the variable name "$scope" is magic. I think we can do something involving making an angular "Provider"; at least, if I take a simple controller and change instances of $scope to sscope or epocs$, then I get a javascript runtime error like:

Error: Unknown provider: epocs$Provider <- epocs$

@chreekat
Copy link
Author

I only arrived at attaching my methods to $scope by trial and error, and perhaps it's not the best solution.

Here's the mental model I've developed so far: in the html template, declare "reactive values" and the relations between them. In Fay, declare the auxiliary data and functions used in the relations. In javascript, wire up the template to the code.

I had this:

<!-- hamlet -->
<input ng-model="x">
<input ng-model="y">
someFunction(x, y) = {{Strict.Foo.someFunction(x, y)}}

and that did not work. But by adding someFunction to $scope, and changing the equation to {{someFunction(x,y)}}, magically I got reactive output! :)

@btford
Copy link

btford commented Oct 24, 2013

Hello all. I'm a newbie to Haskell, but I am a core contributor to AngularJS and was hoping to offer that expertise to this discussion.

AngularJS 1.2 introduces a controller as syntax that I believe would be useful. Instead of:

someModule.controller('MyCtrl', function ($scope) {
  $scope.myMethod = function () { /* ... */ };
});
<div ng-controller="MyCtrl">
  <a href ng-click="myMethod()">do it</a>
</div>

You can now do:

function MyCtrl () { /* ... */ }
MyCtrl.prototype.myMethod = function () { /* ... */ };
someModule.controller('MyCtrl', MyCtrl);
<div ng-controller="MyCtrl as ctrl">
  <a href ng-click="ctrl.myMethod()">do it</a>
</div>

The new controller as syntax is considered best practice (since it makes ambiguous cases much more obvious), so I'd recommend using it anyway besides it possibly being an easier compile target.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants