Giter Site home page Giter Site logo

a1atscript's People

Contributors

davidsouther avatar gitter-badger avatar hannahhoward avatar igorminar avatar lily-mara avatar naomiblack avatar timkindberg avatar vojtajina 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  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

a1atscript's Issues

jspm support

would be great to know how to use it with jspm. (I tried several ways but without success)

JSMP - format global - not helping

I am using a1atscript with JSPM + Typescript in a test project
I assumed I can import a1atscript since you added format global in package.json
but format global is causing errors. I have remove following to make it work.

jspm_packages/npm/[email protected]/dist/a1atscript.bundle.js

/* */ 
"format global";

Is New Router required to use the Angular 2 syntax?

Ready for your first tech support issue? :) Cool project by the way!!

I'm trying to use the Angular 2 syntax, like this:

// main.js
import 'babelify/polyfill';
import 'angular';
import {AsModule, Component, View, bootstrap} from 'a1atscript';

@AsModule('list', [])
@Component({
    selector: "app"
})
@View({
    inline: "<div><h1>App Loaded</h1></div>"
})
class ListApp {
}

bootstrap(ListApp);
// index.html
<app></app>

I am seeing nothing, am I missing something? I see within your bootstrap function here...

export function bootstrap(appModule, appPrefix = "") {
  var injector = new Injector(appPrefix);
  var moduleName = injector.instantiate(appModule);
  Router.routeInitializer.initialize(moduleName, appModule);
}

...you are initializing the module with the Router. Is that the ng1 router or the ng2 router? I'd prefer not to use the ng2 router just yet. In fact I'd like to not use any router just yet. Also when I tried to add ng-app="list' to my index.html, that threw an error.

I'm seeing go into your library's code and it gets all the way through RouteInitializer.initialize, but then no more code seems to run...

Add some way to mimick the various dependency injections in ng2 (@Parent, @Query, etc)

See: https://angular.io/docs/js/latest/api/annotations/DirectiveAnnotation-class.html. There are various dependencies you can inject into the controller class constructor.

  1. directive:DirectiveType: a directive on the current element only
  2. @Ancestor() directive:DirectiveType: any directive that matches the type between the current element and the Shadow DOM root. Current element is not included in the resolution, therefore even if it could resolve it, it will be ignored.
  3. @Parent() directive:DirectiveType: any directive that matches the type on a direct parent element only.
  4. @Query(DirectiveType) query:QueryList<DirectiveType>: A live collection of direct child directives.
  5. @QueryDescendants(DirectiveType) query:QueryList<DirectiveType>: A live collection of any child directives.

In angular 1:

  • 1 is similar to using a require: 'dependency'. So no implementation needed.
  • 2 & 3 are similar to `require: '^depencency'. So no implementation needed.
  • 4 & 5 don't have a direct correlation in ng1. We'd have to write a custom method that queried child directives and watched for changes so it was live. Also the found children would have to properly reference each child's controller class instance.

Thoughts on 4 & 5: Perhaps an api like this would be possible, where we auto-generate a $Query method on every component class that would help with this:

@Component({ selector: 'child-a' })
class ChildA {
  foo() { console.log('foo') }
}

@Component()
@View({
  inline: `
    <child-a/>
    <child-a/>
  `
})
class MyComponent {
  constructor() {
    let childrenA = this.$Query(ChildA);
    console.log(childrenA.length); // outputs 2
    console.log(childrenA[0].foo()); // outputs 'foo'
  }
}

Adding a 'directives' property in @View that acts as an alias to adding module deps

Similar to #19. Except, where appInjector specifies controller-injected dependencies, directives instead specifies which directives (aka Components) are needed for the view. Both are needed as module dependencies though.

See: https://angular.io/docs/js/latest/api/annotations/ComponentAnnotation-class.html for more info on @view.

Instead of using @AsModule to add our component directive dependencies let's use @view directives.

For example, currently we do this:

@Component({ selector: 'foo' })
class Foo {}

@AsModule('Bar', [Foo])
@Component({
  selector: 'bar'
})
@View({
  inline: `<foo></foo>`
})
class Bar { }

We have to add the Foo component as a module dependency on the Bar component's module. Seems like we could achieve the same thing while also following angular 2 api conventions.

We should be able to do this:

@Component({ selector: 'foo' })
class Foo {}

@Component({
  selector: 'bar'
})
@View({
  directives: [Foo],
  inline: `<foo></foo>`
})
class Bar { }

Notice I left out the @AsModule because it should be able to grab the module off of the Foo class passed into the directives property.

'this' context in event handlers should be a reference to the class where the handler lives

When I'm using the Component events config it hooks up the handler with an incorrect this context. I would expect this to reference the App class instance, but it actually references the Home class instance.

@Component({
  selector: 'home'
})
@View({
  template: "<p>Home</p>",
  // Here I'm setting up a 'foo' event
  events: {
    foo: "foo"
  }
})
class HomeComponent {
  constructor() {
    // See here that I'm adding a property to Home
    this.wtf = "wat?";
  }
}

@AsModule('AppModule', [HomeComponent])
@Component({
  selector: "app"
})
@View({
  // Here I'm using the on-foo event and passing a reference to the App's doFoo method
  inline: `<home on-foo="doFoo"></home>`
})
class AppComponent {
  doFoo() {
    // Here is where things fell apart for me and 'this' was not what I expect
    console.log(this) // HomeComponent {wtf: "wat?"}, expected an instance of AppComponent
  }
}

bootstrap(AppComponent)

bind-attribute being overwritten to undefined in angular 1.4.1

Given using angular 1.4.1 and a component such as this:

import {Component, View} from 'a1atscript';

@Component({
  selector: "child",
  properties: {
    data: 'data'
  }
})
@View({
  inline: `<div>{{child.data | json}}</div>`
})
export default class Child { }

When I use it in another component, like this:

import {Component, View} from 'a1atscript';

@Component({
  selector: "parent"
})
@View({
  inline: `<child bind-data="parent.dataForChild"></child>`
})
export default class Parent { 
  constructor() {
    this.dataForChild = {foo: 'bar'};
  }
}

I end up seeing nothing rendered out in Child. When I look at it in dev tools, I see it set to undefined, then {foo: 'bar'}, then (and here's the problem) undefined again.

What is happening is this:

  1. two attributes are set up by a1atscript on the Child directive, data and bind-data.
  2. data is initialized to undefined, setting Child.data to undefined
  3. bind-data is set via the PropertiesBuilder to {foo: 'bar'}, setting Child.data to undefined
  4. BAD STUFF: data is set to undefined again... wat?! Apparrently via bind again. I traced it to a change made in Angular 1.4.1: https://github.com/angular/angular.js/blame/master/src/ng/compile.js#L1192-L1193

I think the workaround needs to be that a1atscript disallows usage of both the regular attr (attr) and the bound version of the attr (bind-attr). Obviously both attrs need to be set up, but then when the user uses one, it should somehow cancel out the other somehow. So if I use bind-attr, then attr knows to just stay out of the way.

ng-link directive does not work with @RouteConfig blocks

I tried to add some links to your router example in the readme. This is what I ended up with:

@Component({})
@View({
  template: "<p>Sub</p>"
})
class SubComponent {

}

@Component({})
@View({
  template: "<p>Home</p><ng-viewport></ng-viewport>"
})
@RouteConfig({
  path: "/sub", component: SubComponent
})
class HomeComponent {
}

// the AsModule annotation is an extra need to setup Angular's module system on the top level component for now
@AsModule('App', ['ngNewRouter', HomeComponent, SubComponent])
@Component({
  selector: "awesome"
})
@View({
  template: `
        <a ng-link="sub">sub</a>
        <a router-link="home">home</a>
        <ng-viewport></ng-viewport>
    `
})
@RouteConfig({
  path: "/home", component: HomeComponent
})
class AppComponent {
}

bootstrap(AppComponent)

Notice the ng-link and router-link in the AppComponent template. I wasn't sure what the correct directive name was. This seems to line up with the official documentation, but when I load the page, the ng-link has an href of "." and therouter-link has no href. Is there something wrong with the way I'm using these directives, or is a1atscript doing something unexpected with the RouteConfig?

Simplified annotation defs

As is, every annotation needs two closely coupled classes, but there doesn't seem to be a reason for that.

You need the annotation itself and the annotationInjector that does the actual work. The injector tends to be in a class heirarchy, but the annotation doesn't. There isn't any overlap of methods.

Consider unifying these classes - just apply the instatiate method of found annotations as we go.

Single annotation per thing

If I understand it correctly, _getDependencyType(dependency) stops at the first annotation it finds. The initial motivation (replace angular.thing calls) only needs that, it might be nice to be able to build up a library of annotations, which means handling multiples.

Which opens the question: what if a single class is annotated (e.g.) @service and @controller?

@Filter could be simpler

Stock Angular 1.3:

angular.module(...).filter("name", function(){
  return function(string, expression){ ... }
})

Since every filter follows this pattern, and stateful or injected filters are discouraged, perhaps A1 could do:

@Filter
export default function(string, expression){ ... }

(at the moment, the wrapping provider function is required)

Using the 'appInjector' property in @Component as an alias to adding module deps

The latest Angular 2 has renamed injectables to appInjector. See: https://angular.io/docs/js/latest/api/annotations/ComponentAnnotation-class.html.

In addition to renaming this, I think we should consider allowing appInjector to take not only string-based ng1 injectables (e.g. '$http') but also a1atscript created injectables (e.g. Greeter).

For example, currently we do this:

@Service('greeter')
class Greeter {}

@AsModule('GreetCmpt', [Greeter])
@Component({
  selector: 'greet',
  injectables: ['$http', 'greeter']
})
class HelloWorld {
  constructor($http, greeter) {
    this.greeter = greeter;
  }
}

We have to add the Greeter service as a module dependency on the Greet component's module. Then also add it to injectables. Seems like we could reduce some boilerplate here.

We should be able to do this:

@Service
class Greeter {}

@Component({
  selector: 'greet',
  appInjector: ['$http', Greeter]
})
class HelloWorld {
  constructor($http, greeter) {
    this.greeter = greeter;
  }
}

In this example I've renamed injectables to appInjector but I've now added the ability to not only inject string-based things like '$http' but also the Greeter service. This more closely matches how ng2 uses classes instead of strings. Also, notice I left out the @AsModule because it should be able to grab the module off of the Greeter class passed into the appInjector.

So the acceptance criteria for this feature would be:

  1. Rename injectables to appInjector
  2. Allow passing a1atscript class-based injectables in addition to string-based regular ng1 injectables
  3. Add the modules from a1atscript classes in appInjector to the dependencies of the auto-generated module of the host class.
  4. If @AsModule is present then merge the dependencies, also allow @AsModule to only specify a name and no dependencies, e.g. @AsModule("GreetComponent")

Component 'properties' and 'events' should be an array

The 'properties' config property in @component has been changed to an array syntax. So we need to update it to instead of:

@Component({
    properties: {
        foo: 'foo',
        bar: 'baz'
    }
})

We need it to be:

@Component({
    properties: ['foo', 'localName: externalName']
})

I might fix this soon, but wanted to post it in case anyone wants to submit a pull request. Shouldn't be hard.

bower.json file references unbundled files

The bower.json file references the following files:

 "main": [
    "dist/a1atscript.js",
    "dist/a1atscript/annotations.js",
    "dist/a1atscript/DirectiveObject.js",
    "dist/a1atscript/Injector.js",
    "dist/a1atscript/injectorTypes.js",
    "dist/a1atscript/ToAnnotation.js",
    "dist/a1atscript/Router.js",
    "dist/a1atscript/bootstrap.js",
    "dist/a1atscript/AnnotationFinder.js",
    "dist/a1atscript/ng2Directives/Component.js",
    "dist/a1atscript/ng2Directives/ComponentInjector.js",
    "dist/a1atscript/ng2Directives/Ng2Directive.js",
    "dist/a1atscript/ng2Directives/Ng2DirectiveDefinitionObject.js",
    "dist/a1atscript/ng2Directives/SelectorMatcher.js",
    "dist/a1atscript/ng2Directives/BindBuilder.js",
    "dist/a1atscript/ng2Directives/EventsBuilder.js",
    "dist/a1atscript/ng2Directives/PropertiesBuilder.js",
    "dist/a1atscript/router/ComponentMapper.js",
    "dist/a1atscript/router/RouteConfig.js",
    "dist/a1atscript/router/RouteInitializer.js",
    "dist/a1atscript/router/RouteReader.js"
  ],

Those are not part of the repo since the files are bundled.

Need to update @Directive so it acts like the ng2 annotation

See: https://angular.io/docs/js/latest/api/annotations/DirectiveAnnotation-class.html

@directive is basically a @component without a view. So its a directive that alters the behavior of an element. So we should be able to use it just like @component, like this;

@Directive({
  selector: '[dependency]',
  properties: ['id']
})
class Dependency { }

I know right now @directive is an ng1 decorator for basically doing ng1 style directive declaration. But I think a1atscript should focus on being a pure ng2 polyfill (my two cents).

add a `host` property to @Directive

See: http://victorsavkin.com/post/119943127151/angular-2-template-syntax. Scroll down to where he implements ng-model from scratch. Here's his code:

@Directive({
  selector: '[ng-model]',
  properties: ['ngModel'],
  events: ['ngModelChanged: ngModel'],
  host: {
    "[value]": 'ngModel',
    "(input)": "ngModelChanged.next($event.target.value)"
  }
})
class NgModelDirective {
  ngModel:any; // stored value
  ngModelChanged:EventEmitter; // an event emitter
}

See how it's possible to add host events, surrounded with '( )', and host property bindings, surrounded with '[ ]'. I feel like this should be possible. Behind the scenes we can get a reference to the element, perhaps from the link function and add the watches and/or event listeners and bind them to the controller class fields and methods.

Depends on #20

Angular 1.4.1 trying to access non-existing getters for hidden properties and getting undefined

To reproduce:

import {AsModule, Component, View} from 'a1atscript';

@Component({
  selector: "parent",
  properties: {
    data: 'data'
  }
})
@View({
  inline: `
    <div>This data won't show: {{ parent.data | json }}</div>
    <child bind-data="parent.data"></child>
`
})
export default class ParentComponent { }

@Component({
  selector: "child",
  properties: {
    data: 'data'
  }
})
@View({
  inline: `<div>This data will show: {{ child.data | json }}</div>`
})
export default class ChildComponent { }

@Component({
  selector: "app"
})
@View({
  inline: `<parent bind-data="app.data"></parent>`
})
export default class App { 
    constructor() {
        this.data = {foo: 'bar'}
    }
}

In this scenario, with data cascading from the top-level all the way through two nested components, we are seeing an issue where the data is not shown in the intermediate levels, parent. We've tracked this to a piece of angular.js code that is trying to access the value of our hidden properties—"_@prop" and "=_prop". However, there are now getters set up for those properties so they are returning undefined and forcing a codepath that believes the data needs to be inherited from the scope chain.

Adding getters should fix this.

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.