npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

angular.haxe

v0.0.3

Published

Toolset for integration of angular.js (https://angularjs.org) in haxe applications

Downloads

5

Readme

angular.haxe

angular.haxe is a toolset for integration of angular.js in haxe applications. It tries to combine angular.js with the type safety of haxe as much as possible. The angular API is fully typed and haxe macros extend the api to support dependency injection based on types instead of unsafe strings.

It's currently incomplete, feel free to add pull requests or become a contributor.

Example of angular.haxe dependency injection

// a regular haxe model
class Config {
	public var appName = "News App";
	public function new () {}
}

class Main
{
	static function main ()
	{
		// controller definition, the parameter types determine
		// which dependencies needs to be injected.

		function appController (scope:Scope, config:Config) {
			trace("appController initialized");
			scope.set("data", { appName : config.appName });
		};

		// module definition

		var module =
			Angular.module("myModule", [])
			// no need give the factory a name,
			// the link is created by the types
			.factory(Config.new)
			.controller("AppController", appController);
	}
}
<html>
<head>
	<title>Angular-Haxe</title>
</head>
<body ng-app="myModule" ng-controller="AppController">
	<h1>{{data.appName}}</h1>
</body>
</html>

See Sample 2 for a slightly larger working example. The generating js file for this example can be found here.

angular.haxe vs angular.js

here are same snippets which highlight differences of angular.haxe vs pure angular.js

Factory / Service registration with dependencies

Factory registration with js.


function MyService (timeout, location) {
	// do something with timeout and location
}

// register as factory
angular.module("myModule", [])
	.factory("myService", ["$timeout", "$location", function (timeout, location) {
		return new MyService(timeout, location);
	}])

In angular.haxe dependency injection in general is based on the type to achieve more type safety. This type gets translated into a string at compile time, e.g. my.pack.MyService becomes "my.pack.MyService". This translation is done through macros which run at compile time and convert the abstract syntax tree in such a way that the generated code is very similar to the js code.

import angular.service.Timeout;
import angular.service.Location;
import angular.Angular;

class MyService {
	public function new (timeout:Timeout, location:Location) {
		// do something with timeout and location
	}
}

// register as factory
Angular.module("myModule", [])
	.factory(MyService.new);

This generated js code looks similar to the next snippet.


function MyService { .... }

Angular.module("myModule", [])
	.factory("MyService", ["$timeout", "$location", function (a1, a2) {
		return new MyService(a1,a2)
	}]);

You may wonder why a type of a core angular services like Timeout are translated to $timeout instead of "angular.service.Timeout". The reason for this is that the core types are annotated with speacial metadata like @:injectionName("$timeout"). Types with this metadata are handled in special way inside of macros like factory, the value inside of this metadata is used instead of the full qualified class name.

Controller

Controller in angular.js

angular.module("myModule", [])
	.factory("myService", ["$timeout", "$location", function (timeout, location) {
		return new MyService(timeout, location);
	}])
	.controller("MyController", ["$scope", "myService", function (scope, myService) {
		// do something in your controller
	}])

The same logic in haxe

Angular.module("myModule", [])
	.factory(MyService.new);
	.controller("MyController", function (scope:Scope, myService:MyService) {
		// do something
	})

Directives

Directive in angular.js

angular.module("myModule", [])
	.directive('myDialog', function() {
	    return {
	      restrict: 'E',
	      transclude: true,
	      scope: {},
	      templateUrl: 'my-dialog.html',
	      link: function (scope, element) {
	        scope.name = 'Jeff';
	      }
	    };
	  });

While you can define the directive in the same way (very dynamic), you can also use the class angular.support.DirectiveBuilder to create a directive. This class is a DSL to build a directive step by step. Note that the link function requires all five supported parameters instead of just the 2 like in the js version. But you can also write function (scope:Scope, e:Element, _,_,_) { if you don't require the last parameters.

Angular.module("myModule", [])
	.directive('myDialog',
		DirectiveBuilder.mk()
			.restrictToElement()
			.transclude(true)
			.isolatedScope()
			.templateUrl('my-dialog.html')
			.link(function (scope:Scope, e:Element, a:Attributes, c:Controller, t:TranscludeFn) {
				scope.set("name", "Jeff");
			})
			.build
	);

Advanced Topics

Typed Scope

import angular.*;
import angular.service.*;

typedef AppScope = { data : { firstName : String, lastName : String }};

class Main
{
	static function main ()
	{
		function appController (t:TypedScope<AppScope>) {
			t.data = {
				lastName : "tom",
				firstName : "timmy"
			};
		}
		var module =
			Angular.module("myModule", [])
			.controller("AppController", appController);


	}
}

Using the same type for multiple services

In order to use the same type for multiple services typedefs (aliases) can be used. This is possible because this library uses macros to inspect the injected types at compilation time and not at runtime.

import angular.*;
import angular.service.*;

typedef Url = String;
typedef Title = String;
typedef Description = String;

typedef AppScope = {
	data : { url : String, title : String, description : String }
};

class Main
{
	static function main ()
	{
		var module =
			Angular.module("myModule", [])
			.factory( function ():Url return "https://github.com/frabbit/angular.haxe")
			.factory( function ():Title return "angular.haxe")
			.factory( function ():Description return "Some words about angular.haxe...")
			.controller("AppController", function (s:TypedScope<AppScope>, url:Url, title : Title, desc:Description) {
				s.data = { url : url, title : title, description : desc };
			});
	}
}

As an alternative the special Const type parameter can be used to distinguish between different Strings by using constant string type parameters.

import angular.*;
import angular.service.*;

typedef CustomString<Const> = String;

typedef AppScope = {
	data : { url : String, title : String, description : String }
};

class Main
{
	static function main ()
	{


		var module =
			Angular.module("myModule", [])
			.factory( function ():CustomString<"url"> return "https://github.com/frabbit/angular.haxe")
			.factory( function ():CustomString<"title"> return "angular.haxe")
			.factory( function ():CustomString<"desc"> return "Some words about angular.haxe...")


			.controller("AppController", function (s:TypedScope<AppScope>, url:CustomString<"url">,
				title : CustomString<"title">, desc:CustomString<"desc">) {

				s.data = { url : url, title : title, description : desc };
			});


	}
}

Functions can be services and are identified by signature

import angular.*;
import angular.service.*;

typedef Title = String;

typedef AppScope = {
	data : { title : String }
};

class Main
{
	static function main ()
	{
		var module =
			Angular.module("myModule", [])
			.factory( function ():Void->Title return function () return "angular.haxe")
			.factory( function ():Title->String return function (t:Title) return "!!! " + t + " !!!")
			.controller("AppController", function (s:TypedScope<AppScope>, getTitle:Void->Title, format:Title->String) {
				s.data = { title : format(getTitle()) };
			});
	}
}

Bundles are auto-composed injectable structures based on other services

package ;

import angular.*;
import angular.service.*;

typedef Bundle = {
	x : String,
	y : Int
};

typedef AppScope = {
	data : { title : String }
};

class Main
{
	static function main ()
	{
		var module =
			Angular.module("myModule", [])
			.factory( function () return 5)
			.factory( function () return "times")
			.bundle( ( _ : Bundle ) )
			.controller("AppController", function (s:TypedScope<AppScope>, bundle:Bundle) {
				s.data = { title : bundle.y + " " + bundle.x };
			});
	}
}

Technically .bundle( ( _ : Bundle ) ) this is just a shortcut for the following code. It becomes really useful for larger bundles with a lot of fields.

.factory( function (x:String, y:Int):Bundle {
	return { x : x, y : y}
})