What is the goal?
- Use of Angular Components with multiple templates.
- Usage of TypeScript for productivity.
- Calling the components in different ways.
I won't write all the code here. Instead, you can download the full source code from the link mentioned at the end of this article.
Let's get started!
Here, person is a component. You can edit, insert or view that person. The same component can have multiples views.
The component is created using the list layout.
- <fsl-pessoa layout="lista-edicao"
- model="$ctrl.pessoas"
- on-event="$ctrl.onChanges(pessoa, evento, index)"></fsl-pessoa>
Each component has some properties.
- "layout" - the layout name for component. There are two layouts: one is the list of persons; second is the edit of a person.
- "model" - the object model to populate the component.
- "on-event" - the change event of the component.
The component using the edit layout.
- <fsl-pessoa layout="edicao"
- model="$ctrl.pessoa"
- on-event="$ctrl.onChanges(pessoa, evento, index)"></fsl-pessoa>
Defining the Angular Component.
- (() => {
-
- class PessoaComponent implements ng.IComponentOptions {
-
- bindings: { [binding: string]: string };
- controller = App.Pessoa.PessoaComponentController;
-
- templateUrl = ['util', '$attrs', (util: App.IUtilProvider, $attrs: ng.IAttributes) => {
- return util.buildTemplateUrl('pessoa/pessoa', $attrs['layout'] || '');
- }];
-
- constructor() {
- this.bindings = {
- model: '<',
- onEvent: '&'
- };
- }
-
- }
-
- angular
- .module('app.pessoa')
- .component('fslPessoa', new PessoaComponent());
-
- })();
The Angular component's Controller.
- namespace App.Pessoa {
-
- export class PessoaComponentController implements ng.IComponentController {
-
- model: App.Pessoa.IPessoa | App.Pessoa.IPessoa[];
- pessoa: App.Pessoa.IPessoa;
- pessoas: App.Pessoa.IPessoa[];
- onEvent: (values: any) => void;
-
- constructor(
- private util: App.IUtilProvider
- ) {
-
- }
-
- $onInit = () => {
- this.receberModel(this.model);
- }
-
- $onChanges = (changes) => {
- if (!changes.model.isFirstChange()) {
- this.receberModel(changes.model.currentValue);
- }
- }
-
- incluirPessoa = () => {
- var pessoa = this.criarNovaPessoa();
- this.pessoas.push(pessoa);
- this.dispararEvento("incluir", pessoa);
- }
-
- excluirPessoa = (pessoa: App.Pessoa.IPessoa) => {
- var index = this.pessoas.indexOf(pessoa);
- this.pessoas.splice(index, 1);
- this.dispararEvento("excluir", pessoa);
- }
-
- editarPessoa = (pessoa: App.Pessoa.IPessoa) => {
- this.dispararEvento("editar", pessoa);
- }
-
- salvarPessoa = () => {
- this.dispararEvento("salvar", this.pessoa);
- this.pessoa = this.criarNovaPessoa();
- }
-
- private criarNovaPessoa = () => {
- return {
- id: this.util.generateGuid()
- }
- }
-
- private dispararEvento = (evento: string, pessoa: App.Pessoa.IPessoa, index?: number) => {
- if (angular.isDefined(this.onEvent)) {
- this.onEvent({ pessoa: pessoa, evento: evento, index: index });
- }
- }
-
- private receberModel = (model: App.Pessoa.IPessoa | App.Pessoa.IPessoa[]) => {
- if (model) {
- if (angular.isArray(model)) {
- this.pessoas = <App.Pessoa.IPessoa[]>model;
- } else {
- angular.copy(<App.Pessoa.IPessoa>model, this.pessoa);
- }
- }
-
- this.pessoa = this.pessoa || this.criarNovaPessoa();
- this.pessoas = this.pessoas || [];
- }
-
- }
-
- PessoaComponentController.$inject = [
- 'util'
- ];
-
- }
Basically, Angular component best practices must be.
- Stateless don't change the model outside the component
- Events if any changes occusr inside a component, fire them using events
- Reusable create the component to be reusable anywhere
The Angular Life Cycle events*.
- "constructor" in the creation;
- $onInit in first init;
- $onChanges when the model changes inside or outside the component;
There are other events. For more information, please check Angular API reference.
Very Important
In the component (code), fire the custom event passing the parameters inside an object.
- this.onEvent({ pessoa: pessoa, evento: evento, index: index });
In usage of component (html), declare the custom event using the same parameter name and order.
- on-event="$ctrl.onChanges(pessoa, evento, index)"
In code callback (code), receive the custom event using the same parameter name and order.
- onChanges = (pessoa: App.Pessoa.IPessoa, evento: string) => {
-
- console.log(evento, this.pessoa);
-
- }