What is best practice to create an AngularJS 1.5 component in Typescript?
Solution 1
If you wanted to completely adopt an Angular 2 approach, you could use:
module.ts
import { MyComponent } from './MyComponent';
angular.module('myModule', [])
.component('myComponent', MyComponent);
MyComponent.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
}
}
decorators.ts
/// <reference path="../typings/angularjs/angular.d.ts" />
export const Component = (options: ng.IComponentOptions) => {
return controller => angular.extend(options, { controller });
};
Solution 2
I am using a simple Typescript decorator to create the component
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 }));
}
}
so I can use it like this
@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--;
}
}
You can try a working jsbin here http://jsbin.com/jipacoxeki/edit?html,js,output
Solution 3
This is the pattern I use:
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());
Solution 4
I was struggling with the same question and put my solution in this article:
http://almerosteyn.github.io/2016/02/angular15-component-typescript
module app.directives {
interface ISomeComponentBindings {
textBinding: string;
dataBinding: number;
functionBinding: () => any;
}
interface ISomeComponentController extends ISomeComponentBindings {
add(): void;
}
class SomeComponentController implements ISomeComponentController {
public textBinding: string;
public dataBinding: number;
public functionBinding: () => any;
constructor() {
this.textBinding = '';
this.dataBinding = 0;
}
add(): void {
this.functionBinding();
}
}
class SomeComponent implements ng.IComponentOptions {
public bindings: any;
public controller: any;
public templateUrl: string;
constructor() {
this.bindings = {
textBinding: '@',
dataBinding: '<',
functionBinding: '&'
};
this.controller = SomeComponentController;
this.templateUrl = 'some-component.html';
}
}
angular.module('appModule').component('someComponent', new SomeComponent());
}
Solution 5
I'm using the following pattern to use angular 1.5 component with typescript
class MyComponent {
model: string;
onModelChange: Function;
/* @ngInject */
constructor() {
}
modelChanged() {
this.onModelChange(this.model);
}
}
angular.module('myApp')
.component('myComponent', {
templateUrl: 'model.html',
//template: `<div></div>`,
controller: MyComponent,
controllerAs: 'ctrl',
bindings: {
model: '<',
onModelChange: "&"
}
});
kpg
I have a great breadth of experience in business and technology gained over many years working in many different roles in every type of organisation in several countries around the world. I am an ICF certified coach. I am a Zoho consultant and a director of Appz Ltd, A Zoho Partner based in Malta but still like to get my hand dirty writing Typescript/Javascript for Node.js and Zoho Catalyst.
Updated on September 23, 2020Comments
-
kpg almost 4 years
I am experimenting with the
.component()
syntax in Angular 1.5.It seems that the latest fashion is to code the controller in-line in the component rather that in a separate file, and I can see the advantage of that given that the component boilerplate is minimal.
The problem is that I having been coding my controllers as typescript classes and would like to continue doing so because that seems to be consistent with Angular2.
My best effort is something like this:
export let myComponent = { template: ($element, $attrs) => { return [ `<my-html>Bla</my-html>` ].join('') }, controller: MyController }; class MyController { }
It works, but it's not elegant. Is there a better way?