mgechev / aspect.js

JavaScript library for aspect-oriented programming using modern syntax.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Waiving a Component

MathieuNls opened this issue · comments

Hi,

Thanks for your library.

I am trying to use wove on an Angular2 component and it breaks the component behaviour:

import { LoggerAspect } from './../../aspects/logger.aspect'

@Component({
  selector: 'app-login',
  templateUrl: 'base/dist/app/directives/login/login.component.html',
  // styleUrls: ['app/directives/login/login.component.css'],
  pipes: [TranslatePipe],
  providers: [TwAPIService, HTTP_PROVIDERS],
  directives: [FORM_DIRECTIVES, MD_BUTTON_DIRECTIVES]
})
@Wove(LoggerAspect)
/**
 * Login component. Provides a login form with controlled and
 * emits a User ($event userLogged) on successful login.
 */
export class LoginComponent implements OnInit 

LoggerAspect contains the @beforeMethod annotation and some console.log statements in the same fashion as the demo.

This transpiles just fine but, upon execution, I got EXCEPTION: Error: Uncaught (in promise): TypeError: Cannot read property 'bind' of undefined.

In your opinion, is it doable at all ?

Thanks.

It works well for me:

import { Component, OnInit } from '@angular/core';
import { REACTIVE_FORM_DIRECTIVES } from '@angular/forms';

import { NameListService } from '../shared/index';

import { Wove, beforeMethod } from 'aspect.js';

class Aspect {
  @beforeMethod({
    classNamePattern: /^HomeComponent$/,
    methodNamePattern: /^addName$/
  })
  before() {
    console.log('Before method...');
  }
}


@Wove()
@Component({
  moduleId: module.id,
  selector: 'sd-home',
  templateUrl: 'home.component.html',
  styleUrls: ['home.component.css'],
  directives: [REACTIVE_FORM_DIRECTIVES]
})
export class HomeComponent implements OnInit {

  newName: string = '';
  errorMessage: string;
  names: any[] = [];

  constructor(public nameListService: NameListService) {}

  ngOnInit() {
    this.getNames();
  }

  getNames() {
    this.nameListService.get()
                     .subscribe(
                       names => this.names = names,
                       error =>  this.errorMessage = <any>error
                       );
  }

  addName(): boolean {
    // TODO: implement nameListService.post
    this.names.push(this.newName);
    this.newName = '';
    return false;
  }

}

You don't have to pass the aspect to @Wove. The idea of this decorator is to set some metadata which needs to be passed to the aspect as parameter. For instance the Angular bindings of aspect.js pass the ElementInjector itself:

import {Router, Injectable} from '@angular/router';
import {beforeMethod, Metadata} from 'aspect.js';
import {Wove} from 'aspect.js-angular';

class SampleAspect {
  @beforeMethod({
    classNamePattern: /^Bar$/,
    methodNamePattern: /baz$/
  })
  logger(meta: Metadata) {
    meta.woveMetadata.injector.get(Router).navigate(['Home']);
  }
}

@Wove()
@Injectable()
class class Bar {
  baz() {
    // method content
  }
}

For details, take a look at the integration with angular2-seed here. The actual woven component can be found here.

@mgechev, Thanks for your quick reply.

I managed to make it work using your examples.