GithubHelp home page GithubHelp logo

angulate2's Introduction

angulate2

Gitter Scala.js

Scala.js bindings for Angular. The goal is to provide an API/ experience very similar to the TypeScript API of Angular.

IMPORTANT: angulate2 currently only supports Scala 2.11.x

A basic Quickstart Example that may serve as template is available, as well as set of extended examples.

Release Notes

Getting Started

SBT settings

Add the following lines to your project/plugins.sbt:

addSbtPlugin("de.surfice" % "sbt-angulate2" % "0.1.0-RC1")

and this to your build.sbt:

enablePlugins(Angulate2Plugin)

ngBootstrap := Some("AppModule") //qualified name (including packages) of Scala class to bootstrap

The current version of angulate2 is built for Angular 4 and Scala.js 0.6.18.

Create application module and component

import angulate2.std._
import angulate2.platformBrowser.BrowserModule

@NgModule(
  imports = @@[BrowserModule],
  declarations = @@[AppComponent],
  bootstrap = @@[AppComponent]
)
class AppModule {}

@Component(
  selector = "my-app",
  template = "<h1>{{greeting}}</h1>
}
class AppComponent {
  val greeting = "Hello Angular!"
}

Build and run with System.js

With the above configuration, a separate JS file PROJECT-sjsx.js is written to target/scala-2.11/ every time you run fastOptJS or fullOptJS. This file contains the class decorators generated from Angular2 annotations (@Component, ...) and represents the entry module of your Angular application. The annotations file loads the Scala.js package and all Angular libraries via require, so you need to load the annotations file with a module loader.

One way to achieve this is to use (System.js)[https://github.com/systemjs/systemjs]. The angulate2 sbt plugin provides some tasks to simplify the creation of the System.js configuration, and for running (lite-server)[https://github.com/johnpapa/lite-server]. Although you can build your angulate2 project without Node.js, some of these tasks require a Node.js installation, so make sure npm and node are in your PATH before you proceed.

Add the HTML index

Create src/main/resources/index-fastopt.html with the following content:

<html>
  <head>
    <title>Angulate2 QuickStart</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- <link rel="stylesheet" href="styles.css"> -->
    <!-- 1. Load libraries -->
    <!-- Polyfill for older browsers -->
    <script src="node_modules/core-js/client/shim.min.js"></script>
    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <!-- 2. Configure SystemJS -->
    <script src="systemjs-fastopt.config.js"></script>
    <script>
      System.import('app').catch(function(err){ console.error(err); });
    </script>
  </head>
  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>
</html>

Create the System.js configuration

Most of the settings required for System.js config file are pre-configured by the angulate2 sbt plugin; however, you need to add the following System.js module mappings to your build.sbt:

    systemJSMappings in fastOptJS ++= Seq(
      "@angular/core"                     -> "npm:@angular/core/bundles/core.umd.js",
      "@angular/common"                   -> "npm:@angular/common/bundles/common.umd.js",
      "@angular/compiler"                 -> "npm:@angular/compiler/bundles/compiler.umd.js",
      "@angular/platform-browser"         -> "npm:@angular/platform-browser/bundles/platform-browser.umd.js",
      "@angular/platform-browser-dynamic" -> "npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js",
      "@angular/http"                     -> "npm:@angular/http/bundles/http.umd.js",
      "@angular/router"                   -> "npm:@angular/router/bundles/router.umd.js",
      "@angular/forms"                    -> "npm:@angular/forms/bundles/forms.umd.js",
      "@angular/upgrade"                  -> "npm:@angular/upgrade/bundles/upgrade.umd.js",
      "rxjs"                              -> "npm:rxjs"
    )

then run sbt fastOptJS::systemJS. This creates the System.js configuration at target/scala-2.11/systemjs-fastopt.config.js.

Create lite-server configuration

Next run sbt fastOptJS::liteServerWriteConfigFile. This will install all required npm dependencies (which may take some time), copy your index-fastopt.html to target/scala-2.11/, and create bs-config-fastopt.json (the lite-server configuration).

Compile and run project

Run sbt fastOptJS; this will build the Scala.js application file (angulate2-quickstart-fastopt.js) and the corresponding decorator file (angulate2-quickstart-sjsx.js). To run you project, start

$ node_modules/lite-server/bin/lite-server --config=target/scala-2.11/bs-config-fastopt.json

from your shell, and point your browser to http://localhost:3000/index-fastopt.html.

Bundle the application with webpack

TBD

License

This code is open source software licensed under the MIT License.

angulate2's People

Contributors

gumdrop avatar jokade avatar mardo avatar n3phtys avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angulate2's Issues

Support enbaleProdMode()

Set

ngEnableProdMode := true

in build.sbt to enable Angular's production mode (i.e. core.enableProdMode() will be called at runtime).

Extension: derive providers from constructor arg

It should be possible to derive the providers array requried by Angular2 DI from the primary constructor, i.e.

@Component(
  selector = "foo"
)
class FooComponent(http: Http, bar: BarService) {
  /* ... */
}

should be equivalent to

@Component(
  selector = "foo"
  providers = @@[Http,BarService]
)
class FooComponent(http: Http, bar: BarService) {
  /* ... */
}

However, an explicitly set providers property overwrites the derived DI array.

Design goals

I'd like to start a discussion on some basic design goals / rules for this binding, e.g.

  • coding experience / API style: I'd prefer to keep the binding as close as possible to the Typescript API of Angular2, and only deviate where necessary (e.g. due to restrictions imposed by macros,etc). One example for such a deviation is the @@[T] operator. In addtion to this basic Typescript-compatible API we could provide enhancements that utilize advanced Scala features (e.g. an efficient DSL for routing, etc)
  • packaging/naming: should we place bindings / façade traits under the angular namespace (instead of angulate2)? Should we include all Angular2 modules in a single angulate2 lib? Or should we provide separate libs for the core and optional addons?
  • release strategy and version numbering: should we mirror the Angular2 release cycle / version numbers to some extent in the angulate2 version number?

Support all lifecycle hooks

Currently supported are ngOnInit and ngOnDestroy. The other 6 https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html are not yet in.

This especially has focus on ngOnChanges, which is triggered every time an input changes. This is especially useful if another property of the Component is supposed to be calculated based on input. There is no simple way to initialize such a property correctly without this lifecycle hook.

Currently no published artifact?

Trying to get the examples working once again, sbt cannot resolve some dependencies anymore.

As far as I see, the 0.1-SNAPSHOT cannot be resolved anymore as it does not appear to be within Sonatype. Will there be a new version published soon?

How to use with playframework

At first: Thanks for your efforts in this project.

I've setup a playframework-scala-js project as shown in vmunier/play-with-scalajs-example. angulate2 works fine as long as I manually copy the generated xxx-sjsx.js file to the server's resource directory. But I cannot find a way to provide it automatically whenever it is generated. Any ideas?

BTW: In the README.md for angulate2 below the first code example you write:

Important: Don't forget to load the file target/scala-2.11/annotations.js after the JS files generated by Scala.js!

It took me some time to figure out, that the needed file isn't called annotations.js but sjsx.js.

Validate inputs at compile time

I recently had an issue where is set an input equal to "the-hero". The @Component macro lets this through, but angular throws at runtime since that's not a valid JavaScript identifier. I think it would be fairly simple to validate inputs at compile time inside the macro. You would have to account for the "a:b" syntax of inputs as well. I don't know off the top of my head what the js identifier regex is, but it should be fairly simple. For performance, you could create a pretty simple manual parser as well but for simplicity's sake a simple regex is probably fine.

Use JSExportStatic for Angular annotations

Currently we generate a separate JS file with the annotations required by Angular (-sjsx.js'). With the advent of @JSExportStatic` in Scala.js 0.6.15 this should no longer be necessary.

Handle all field decorators together

We should handle all field decorators (@HostListener, @HostBinding, etc) in a single decorator trait instead of separate traits for each annotation.

Interop with TypeScript doesn't work for components

I'm trying to migrate a project slowly to scala.js and am having trouble getting my components to be recognized in my (TypeScript) NgModule definition.

I import the symbol for the component

import scalajs from './common/scala.js'

and then reference it as:

scalajs.com.transit.MyRegions

but get the error:

Unexpected value '$c_Lcom_transit_MyRegions' declared by the module 'AppModule'

Error: Unexpected value '$c_Lcom_transit_MyRegions' declared by the module 'AppModule'
    at http://localhost:8100/build/main.js:31990:27
    at Array.forEach (native)
    at CompileMetadataResolver._loadNgModuleMetadata (http://localhost:8100/build/main.js:31970:54)
    at CompileMetadataResolver.loadNgModuleMetadata (http://localhost:8100/build/main.js:31893:29)
    at RuntimeCompiler._loadModules (http://localhost:8100/build/main.js:47271:41)
    at RuntimeCompiler._compileModuleAndComponents (http://localhost:8100/build/main.js:47241:35)
    at RuntimeCompiler.compileModuleAsync (http://localhost:8100/build/main.js:47231:21)
    at PlatformRef_._bootstrapModuleWithZone (http://localhost:8100/build/main.js:34121:25)
    at PlatformRef_.bootstrapModule (http://localhost:8100/build/main.js:34103:21)
    at Object.<anonymous> (http://localhost:8100/build/main.js:123863:124)

hunting through the JavaScript I see that this is because it fails to reflectively find the annotations (Decorators) whereas for components defined in TS this succeeds.

I've tried adding @classModeJS but this makes no difference.

Using version 0.0.5

Extension: Routes() annotation

Simplify creation of routing modules:

@Routes(
  root = true,
  Route(path = "/heroes", component = %%[HeroesComponent]),
  Route(path = "**", component = %%[PageNotFoundComponent] )
class AppRoutingModule

@NgModule(
  imports = @@[AppRoutingModule] )
class AppModule

Generalize Data annotation

Case classes annotated with @Data should be translated into plain JS objects when compiled with Scala.js (and be ignored with Scala/JVM).

Example: when Node is defined as

@Data
case class Node(id: Int, label: Option[String] = None, children: Seq[Node] = Nil)

then

Node(1, label = Some("root"), children = Seq(
  Node(2, label = Some("child1")),
  Node(3)
))

should translate to

{id: 1, label: "root", children: [{id: 2, label: "child1", children: []}, {id: 3, label: undefined, children: []}]}

How Can I Help?

I would love to contribute to this project. Let me know I can be the most help.

Add Angular annotations during compilation?

It would be great, if we could inject the annotations required by Angular from within one of the compiler phases. Thus we could get rid of the separate annotations file currently used.

Requirement on Global Namespace

The facades in this project require angular at a global namespace, but can that be avoided?

It's ideal to work with modules, and the RCs don't provide a namespace-polluting build file. I haven't found a way to get SystemJS to expose ng.

Would import sytax like this be required?

Add README section on limitations

Limitations:

  • don't use moduleId & component relative paths
  • @Directive requires @classModeJS
  • generated metadata for method annotations incomplete
  • companion objects for annotated classes

Provide basic scalatags for built-in directives and bindings

Example in-line scalatags template:

import angulate2.ext.tags.simple._
import scalatags.Text.all._

@Component(
  template = tpl(
   h2("HEROES"),
    div(ngIf:="hero")(
      h3("{{ hero.name }}"),
      div(
        label("Id: "),"{{ hero.id }}",
        input(ngModel:="hero.name", placeholder:="name")
      ),
      p(
        button(ngClick:="gotoHeroes()")("Back")
      )
    )
  )
)
class HeroDetailComponent

Get an Injection Error when injects nothing.

I created a service that annotated with @Injectable like the following

@Injectable
class HeroService {
  val heroes: js.Array[Hero] = js.Array(
    Hero(11, "Mr. Nice"),
    Hero(12, "Narco")
  )
}

it generated annotation.js which contains HeroService.parameters = [[]];.
It seems to be unnecessary and cause an exception.

EXCEPTION: Cannot resolve all parameters for '$c_LHeroService'(?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that '$c_LHeroService' is decorated with Injectable.

when I manually remove the line from annotation.js It performed well.

Automatically generate `providers` parameters based on constructor

Right now you have to do:

@Component(
  providers = @@[FooService, BarService],
  ...
)
class BazComponent(
  fooService: FooService,
  barService: BarService
)

It would be nice to reduce this to:

@Component(
  ...
)
class BazComponent(
  fooService: FooService,
  barService: BarService
)

I think this could be accomplished fairly easily in the @Component macro.

Consolidate annoation macros

All type decorator annotations should use a common ClassDecorator base to simplify maintenance and extensions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.