Code Contribution Guideline - SAP/fundamental-ngx GitHub Wiki

Component structure

export class ComponentName {
    // public @Input() component properties

    // public @Output() component properties
    
    // public other decorated component properties

    // public component properties

    // private other decorated component properties
    
    // private component properties
    constructor() {}

    // lifecycle hooks methods

    // interfaces methods

    // public component methods

    // private component methods
}

Example:

export class ComponentName implements OnInit, OnChanges, OnDestroy, CssClassBuilder {
    // public @Input() component properties
    @Input()
    inp1: string;

    @Input()
    inp2: string;

    @Input()
    inp3: string;

    // public @Output() component properties
    @Output()
    inp1: string;

    @Output()
    inp2: string;

    @Output()
    inp3: string;

    // public other decorated component properties
    @ViewChild()
    viewChild: type

    // public component properties
    prop1: string;
    prop2: string;
    prop3: string;

    // private other decorated component properties
    @ViewChild()
    private _viewChild2: type
    
    // private component properties
    private _prop1: string;
    private _prop2: string;
    private _prop3: string;

    constructor() {}
    // lifecycle hooks methods
    ngOnInit(): void {}

    ngOnChanges(): void {}

    ngDestroy(): void {}

    // interfaces methods
    buildComponentCssClass(): string {
        return '';
    }

    // public component methods
    method1(): void {}
    method2(): void {}
    method3(): void {}

    // private component methods
    private _method4(): void {}
    private _method5(): void {}
    private _method6(): void {}
}

Method and Variable naming convention

  • public: lowerCamelCase. Example: firstName, addProductToShopCart()
  • private: lowerCamelCase with _ prefix. Example: _firstName, _addProductToShopCart()
  • Properties/Decorators: variable declaration should starts from newline from decorator. Example
  • static variable should use UPPER_SNAKE_CASE
  • public access modifiers are included by default and can be skipped,
  • private access modifiers must be added to private properties and methods
/** Bad Usage */
@Input() disabled: boolean = false;

/** Good Usage */
@Input()
disabled: boolean = false;

Comments

  • Comments should be consistent for methods and variables in *.ts files. They should be added directly above the commented property.
/** Example of 1 line comment */
firstName: string = '';

/** 
 * Example of comment with 
 * text longer than 1 line
 */
firstName: string = '';
/** 
 * @hidden
 * Example of comment for cycle method, that requires some comment
 */
private _removeList(): void {}

/** @hidden */
private _propertyWithoutComment: string;

Angular

  • All components should have changeDetectionStrategy.OnPush. It improves the performance of the library.

Building component css classes

In order to build css classes for components, the rules listed below must be used:

  • Component has to implement both CssClassBuilder and OnChanges interfaces
export class RadioButtonComponent implements OnChanges, OnInit, CssClassBuilder
  • buildComponentCssClass() method must be implemented as seen in the following example:
    @applyCssClass
     /** This method is responsible for building a css class based on current state
      *  It is implementation of CssClassBuilder interface and
      *  should be used with @applyCssClass decorator
      */
    buildComponentCssClass(): string {
        return [
            'fd-radio',
            this.compact ? 'fd-radio--compact' : '',
            this.state !== 'default' ? `is-${this.state}` : ''
        ].join(' ');
    }

The usage of @applyCssClass is recommended because it hides the logic for applying classes to the component. It is each developer's responsibility to organize the classes in the correct order (see buildComponentCssClass for class order guidelines).

  • ngOnChanges() method must be implemented and must call buildComponentCssClass()
    /** @hidden */
    ngOnChanges(): void {
        this.buildComponentCssClass();
    }
  • ngOnInit method must be implemented and the method has to call buildComponentCssClass()
   ngOnInit(): void {
        this.buildComponentCssClass();
    }

TemplateRef vs Structural directives

When developing component features, it is prefered to use structural directives passed to the component as a @ContentChild(ren) rather than use @Input() with TemplateRef type.

Advantages of using structural directive:

  • Typechecking;
  • Passing data to directive and potentially transform it for further usage inside template block.