Skip to content

Component Project Overview

Details of component development

You can build multiple components in one project or have one project per component. Currently we have a project called sc-components that we build with Angular CLI, using the following command:

ng build sc-components

We also have separate projects per component, sc-components just brings all the components together from their various projects. So a build of an individual component can be done with:

ng build <project-name>

For Example:

ng build sc-text-box

If individual component projects don’t work, it’s because the component project hasn’t been coded correctly because most of our developers haven’t been aware of the separate component projects yet. The building of components in projects containing individual or multiple projects are facilitated by Angular Modules, described at architecture-modules . If you take sc-text-box, it consists of the following files in the formbird-sc-components/projects/sc-text-box/src/app/text-box directory: - text-box.component.html - text-box.component.spec.ts - this is a unit test file that is auto-generated. We haven’t written many tests but the ability to do it is there. These use either the Karma or Jest testing frameworks for testing. Karma is the default for Angular CLI but we have used Jest in the core because it is faster. Jest tests don’t run in a browser. Karma tests run in the browser so it has the advantage of being able to run tests in multiple browsers but this also causes the tests to run so slowly. We decided to use Jest in the core because although it doesn’t have the multiple browser tests it allows us to get tests happening that will cover 90% of cases and there will just be the odd instance of browser incompatibilities that can be picked up with e2e tests developed by Kristian in TestCafe or through manual testing. It was a decision between having some tests going in Jest that don’t have multiple browser support or trying to get the Karma tests going in multiple browsers and ending up with no tests because it’s too hard to get going and the tests are too slow. - text-box.module.ts - This brings together the component and the libraries that it depends on. - text-box.component.scss - this contains the styles for the component. It uses Sass, described at https://sass-lang.com/guide . Sass is like css with extra functionality. It is also possible to use a plain css file. Some Sass Mixins have been developed in an @formbird/styles module that contain standard styles for things like responsive styles - text-box.component.ts - this is the main code file for the component. It has a ts extension because it uses Typescript, which is a superset of Javascript containing types. We have some types in an @formbird/types project that are imported into components: import { ComponentDefinition, FormComponent, FormDocument, FormTemplate } from '@formbird/types'; We then make our components implement the FormComponent Typescript interface. Typescript interfaces are a way to specify the parameters and functions that a Typescript class should contain, as described at interfaces.html. When we implement FormComponent, there will be an error if any of the @Input parameters in FormComponent are missing:

@Component({ 
 selector: 'sc-text-box',
 templateUrl: './text-box.component.html',
 styleUrls: ['./text-box.component.scss'],
 encapsulation: ViewEncapsulation.None,
})
export class TextBoxComponent implements FormComponent, OnInit {
 @Input() document: FormDocument;
 @Input() fieldValue: any;
 @Input() template: FormTemplate;
 @Input() fieldName: string;
 @Input() formParameters: any;
 @Input() key: number;
 @Input() message: string;
 @Input() componentDefinition: TextBoxComponentDefinition;

@Input parameters are Angular parameters that are passed into the component, as described at Input. The componentDefinition was called tplItem in AngularJS but we renamed it to make it more clear what it is. You can see in the example above that componentDefinition is of type TextBoxComponentDefinition. What we do is extend the ComponentDefinition type, which you can see in the core at fieldtec-web/projects/types/src/lib/types/component-definition.type.ts, to include the properties specific to the sc-text-box component. This is from sc-text-box.component.ts:

interface TextBoxComponentDefinition extends ComponentDefinition {
 caption?: string;
 label?: string;
 onClick?: string;
 style?: string;
}

This means the Typescript compiler will recognise the properties from this ComponentDefinition type.

It’s possible to use a type of any for a Typescript variable so type checking will not be used on that variable.

  • projects/sc-text-box/src/app/text-box/text-box.module.ts - this is an Angular Module that specifies the dependencies of the Angular Text Box component. The text-box-component needs to be imported and added to declarations. Word is you don’t need it in entryComponents anymore but we need to confirm this. You need the CUSTOM_ELEMENTS_SCHEMA because we are registering our component as a custom element: ``` declarations: [ TextBoxComponent ],
    schemas: [CUSTOM_ELEMENTS_SCHEMA], entryComponents: [ TextBoxComponent ],

    `` We register our component as a custom element in the constructor of the module. You can see here we register the component assc-text-boxandsc-text-box-web-component. We use theweb-componentsuffix for running in the AngularJS core using a wrapper if we need to. We also can register other names for the same component, such assc-text`:

constructor(private injector: Injector, private customElementService: CustomElementService) {
   customElementService.convertToCustomElement(TextBoxComponent, 'sc-text-box', this.injector);
      // register custom element with web-component suffix so that the suffixed name can be used while transitioning to the
   // angular components when the AngularJS component is still installed
   customElementService.convertToCustomElement(TextBoxComponent, 'sc-text-box-web-component', this.injector);
 }
}

You also need to import the modules for Angular Libraries that you use in the component in the module for the component. A common example is the Angular Material library, at https://material.angular.io/components/input/overview . The text box contains Angular Material elements, prefixed with mat- in the html file for the component:

<mat-form-field>
 <mat-label class="{{componentDefinition.mandatory ? 'mandatory' : ''}}">   
   {{componentDefinition.label}}
 </mat-label>
 ...

These elements won’t be recognised unless you import the module for the library into the module for the component. In the text box module we have imported the Angular Material modules needed to render the Angular Material components and features used:

imports: [
   BrowserModule,
   MatIconModule,
   MatInputModule,

The text box module is imported into the module for any component project that it needs to be built as part of. Each component project has an app.module.ts file, which is a standard Angular module name. TextBoxModule is imported into formbird-sc-components/projects/sc-text-box/src/app/app.module.ts so that the text box component will be included in the build of the sc-text-box project, built with:

ng build sc-text-box

It is also also included in projects/sc-components/src/app/app.module.ts along with modules for other components so sc-text-box will be included in the sc-components project when you build it with:

ng build sc-components