Búsqueda de sitios web

¿Cuál es la mejor práctica para crear un componente de AngularJS 1.5 en TypeScript?


Estoy experimentando con la sintaxis .component() en Angular 1.5.

Parece que la última moda es programar el controlador en línea dentro del componente en lugar de en un archivo separado, y puedo ver la ventaja de eso dado que el código inicial del componente es mínimo.

El problema es que he estado programando mis controladores como clases de TypeScript y me gustaría seguir haciéndolo porque eso parece ser consistente con Angular2.

Mi mejor esfuerzo es algo así:

export let myComponent = {
  template: ($element, $attrs) => {
    return [
      `<my-html>Bla</my-html>`
    ].join('')
  },
  controller: MyController
};
class MyController {

}

Funciona, pero no es elegante. ¿Hay una manera mejor?

Respuesta #1

Si quisieras adoptar completamente un enfoque de Angular 2, podrías usar:

module.ts

import { MyComponent } from './MyComponent';

angular.module('myModule', [])
  .component('myComponent', MyComponent);

MiComponente.ts

import { Component } from './decorators';

@Component({
  bindings: {
    prop: '<'
  },
  template: '<p>{{$ctrl.prop}}</p>'
})
export class MyComponent {

   prop: string;

   constructor(private $q: ng.IQService) {}

   $onInit() {
     // do something with this.prop or this.$q upon initialization
   }
}

decoradores.ts

/// <reference path="../typings/angularjs/angular.d.ts" />

export const Component = (options: ng.IComponentOptions) => {
  return controller => angular.extend(options, { controller });
};

Respuesta #2

Estoy usando un decorador simple de Typescript para crear el componente

function Component(moduleOrName: string | ng.IModule, selector: string, options: {
  controllerAs?: string,
  template?: string,
  templateUrl?: string
}) {
  return (controller: Function) => {
    var module = typeof moduleOrName === "string"
      ? angular.module(moduleOrName)
      : moduleOrName;
    module.component(selector, angular.extend(options, { controller: controller }));
  }
}

así puedo usarlo de esta manera

@Component(app, 'testComponent', {
  controllerAs: 'ct',
  template: `
    <pre>{{ct}}</pre>
    <div>
      <input type="text" ng-model="ct.count">
      <button type="button" ng-click="ct.decrement();">-</button>
      <button type="button" ng-click="ct.increment();">+</button>
    </div>
  `
})
class CounterTest {
  count = 0;
  increment() {
    this.count++;
  }
  decrement() {
    this.count--;
  }
}

Puedes probar un jsbin que funciona aquí http://jsbin.com/jipacoxeki/edit?html,js,output

Respuesta #3

Este es el patrón que uso:

ZippyComponent.ts

import {ZippyController} from './ZippyController';

export class ZippyComponent implements ng.IComponentOptions {

    public bindings: {
        bungle: '<',
        george: '<'
    };
    public transclude: boolean = false;
    public controller: Function = ZippyController;
    public controllerAs: string = 'vm'; 
    public template: string = require('./Zippy.html');
}

ZippyController.ts

export class ZippyController {

    bungle: string;
    george: Array<number>;

    static $inject = ['$timeout'];

    constructor (private $timeout: ng.ITimeoutService) {
    }
}

Zippy.html

<div class="zippy">
    {{vm.bungle}}
    <span ng-repeat="item in vm.george">{{item}}</span>
</div>

main.ts

import {ZippyComponent} from './components/Zippy/ZippyComponent';

angular.module('my.app', [])
    .component('myZippy', new ZippyComponent());

Artículos relacionados