19.1.11 • Published 5 months ago

@lukfel/scaffold v19.1.11

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

Documentation

Introduction

This Angular library provides a foundational scaffold for modern web and mobile applications. It includes essential UI elements such as a header, sidebar, drawer, footer, floating button, and built-in services for theme switching, snackbar notifications, dialog management, and breakpoint detection. Simply wrap your router-outlet with the lf-scaffold element and configure the ScaffoldConfig within the ScaffoldService.

Installation

Install the package using npm:

npm install @lukfel/scaffold

Module

Import the ScaffoldModule into your app.module.ts file.

  • Note: (Optional) The library includes a built-in logging service called Logger, which logs library deugging events when a LibraryConfig is provided and debugging is set to true. Logging is automatically disabled in production mode when prodution is set to true.
import { ScaffoldModule } from '@lukfel/scaffold';
import { isDevMode } from '@angular/core';

@NgModule({
  ...
  imports: [
    ScaffoldModule.forRoot({ production: !isDevMode(), debugging: isDevMode() }),    // Omit .forRoot(...) if logging is not required
  ]
})
export class AppModule { }

Styling

Import the styles in your styles.scss and apply a default theme.

  • Note: The library’s styles include Material icons and Roboto font styles.
@use "@lukfel/scaffold/styles" as lf;
@include lf.scaffold-theme();           // include a default theme

Custom Themes (Optional)

To customize the default theme, define a new theme map specifying primary, accent, and warn colors using Material palettes. Enabling the dark option applies a dark theme. Pass your custom theme to lf.scaffold-theme($my-theme).

@use "@lukfel/scaffold/styles" as lf;
@use '@angular/material' as mat;

$my-theme: (
  primary: mat.define-palette(mat.$pink-palette),
  accent: mat.define-palette(mat.$blue-palette),
  warn: mat.define-palette(mat.$red-palette),
  dark: false
);

@include lf.scaffold-theme($my-theme);

Multiple Themes (Optional)

To switch between multiple themes dynamically, define additional themes using lf.scaffold-colors($theme, 'theme-class'), then apply the class to the <body class="theme-class"> tag.

  • Note: The ThemeService allows dynamic theme switching.
@use "@lukfel/scaffold/styles" as lf;
@use '@angular/material' as mat;

$my-theme: (
  primary: mat.define-palette(mat.$pink-palette),
  accent: mat.define-palette(mat.$blue-palette),
  warn: mat.define-palette(mat.$red-palette),
  dark: false
);

$my-theme2: (
  primary: mat.define-palette(mat.$purple-palette),
  accent: mat.define-palette(mat.$amber-palette),
  dark: false
);

@include lf.scaffold-theme($my-theme);                      // Set the primary theme with lf.scaffold-theme(...)
@include lf.scaffold-colors($my-theme2, 'my-theme2');       // Set additional themes with lf.scaffold-colors(...)

Custom Typography (Optional)

To change the default typography from Roboto, pass an additional parameter font-family in the theme map.

  • Note: Don't forget to also import and set the font-family in the styles.
@use "@lukfel/scaffold/styles" as lf;
@use '@angular/material' as mat;

$my-theme: (
  primary: mat.define-palette(mat.$pink-palette),
  accent: mat.define-palette(mat.$blue-palette),
  warn: mat.define-palette(mat.$red-palette),
  dark: false,
  font-family: 'Comic Sans'
);

@include lf.scaffold-theme($my-theme); 

body {
    font-family: "Comic Sans MS" !important;
}

Template

Wrap your application’s content inside the lf-scaffold component in app.component.html.

<lf-scaffold>
  <!-- (Optional) drawer content shows inside the left drawer if enabled -->
  <ng-container drawerContent></ng-container>
  <router-outlet></router-outlet>
</lf-scaffold>

Configuration

Import the ScaffoldService in app.component.ts to manage the ScaffoldConfig settings.

import { ScaffoldService } from '@lukfel/scaffold';

export class AppComponent {
  constructor(private scaffoldService: ScaffoldService) {}
}

Update Configuration

Define the ScaffoldConfig in app.component.ts and update the scaffoldConfig property in ScaffoldService.

  • Notes:
    • If a sub-configuration (e.g., headerConfig) is missing or does not have enable: true, the corresponding UI element will not be displayed.
    • Refer to the demo project for full configuration details.
import { ScaffoldService, ScaffoldConfig } from '@lukfel/scaffold';

export class AppComponent {

  public scaffoldConfig: ScaffoldConfig = {
    scrollPositionRestoration: true,
    headerConfig: { enable: true, title: 'Scaffold', subtitle: 'by Lukas Felbinger' },
    navbarConfig: { enable: true },
    footerConfig: { enable: true, copyright: '© Lukas Felbinger 2023' },
    floatingButtonConfig: { enable: true }
  };

  constructor(private scaffoldService: ScaffoldService) {
    this.scaffoldService.scaffoldConfig = this.scaffoldConfig;
  }
}

Events

There are two ways to listen to scaffold user events (button clicks, input changes, ...):

Option 1 (Recommended) – Subscribe to Observables

Subscribe to the event Observables and listen to changes

constructor(private scaffoldService: ScaffoldService, private router: Router) {
  // Listen to click events (header menu and navbar buttons - click)
  this.scaffoldService.buttonClickEventValue$.subscribe((id: string) => {
    this.router.navigate([id]);
  });

  // Listen to header input change events (header input field - change)
  this.scaffoldService.headerInputChangeValue$.subscribe((value: string) => {
    ...
  });
}

Option 2 – Use Output Events

Specify the needed output events and call custom methods

<lf-scaffold
  (headerButtonClickEvent)="headerButtonClickEvent($event)"
  (headerInputSubmitEvent)="headerInputSubmitEvent($event)"
  (headerInputChangeEvent)="headerInputChangeEvent($event)"
  (navbarButtonClickEvent)="navbarButtonClickEvent($event)">
  <router-outlet></router-outlet>
</lf-scaffold>
// Listen to header click events (header menu buttons - click)
public headerButtonClickEvent(id: string): void {
  this.router.navigate([id]);
}

// Listen to header input submit events (header input field - submit)
public headerInputSubmitEvent(value: string): void {
  ...
}

// Listen to header input change events (header input field - change)
public headerInputChangeEvent(value: string): void {
  ...
}

// Listen to navbar click events (navbar menu buttons - click)
public navbarButtonClickEvent(id: string): void {
  this.router.navigate([id]);
}

Additional Services

This library includes several utility services:

  • Logger – Development-only logging
  • SnackbarService – Display snackbar notifications
  • DialogService – Display custom dialogs
  • BreakpointService – Detect screen breakpoints
  • ThemeService – Manage themes dynamically
  • RouterService – Track route changes and retreive route history
  • SeoService – Manage meta tags
  • LocalStorageService – Handle local storage

Logger

Logs internal library information if debugging is true and hides application logs during production if production is true.

  • Note: LibraryConfig must be set during initialization ScaffoldModule.forRoot( { production: !isDevMode(), debugging: isDevMode() } )
import { Logger } from '@lukfel/scaffold';

export class AppComponent {

  constructor(private logger: Logger) {}
  
  // Generic api call with logging
  public apiCallWithLogging(): void {
    this.apiService.apiCall().then(result => {
      this.logger.log(result);
    }).catch(error => {
      this.logger.error(error);
    });
  }
}

SnackbarService

Provides basic methods to display simple snackbar notifications with or without actions.

import { SnackbarService } from '@lukfel/scaffold';

export class AppComponent {

  constructor(private snackbarService: SnackbarService) {}
  
  // Generic api call with snackbar response
  public apiCallWithSnackbarResponse(): void {
    this.apiService.apiCall().then(result => {
      this.snackbarService.openSnackbar('Call was successful');
    }).catch(error => {
      this.snackbarService.openSnackbar('Call was not successful');
    });
  }
}

DialogService

Includes a basic confirmation dialog thar returns a Promise. Use the method openCustomDialog to pass your own dialog template and config.

import { DialogService } from '@lukfel/scaffold';

export class AppComponent {

  constructor(private dialogService: DialogService) {}
  
  // Generic api call with a subsequent confirmation dialog
  public apiCallWithDialogConfirmation(): void {
    this.dialogService.openConfirmDialog('Do you really want to make this api call?').then(response => {
      // If the user confirmed the dialog, go through with the api call
      if(response === true) {
        this.apiService.apiCall().then(result => {
          ...
        }).catch(error => {
          ...
        }); 
      }
    });
  }
}

BreakpointService

Allows you to subscribe to breakpoint changes.

import { BreakpointService } from '@lukfel/scaffold';

export class AppComponent {

  constructor(private breakpointService: BreakpointService) {
    this.breakpointService.breakpoint$.subscribe((result: BreakpointState) => {
      // Check which breakpoint is active
      if (result.breakpoints[Breakpoints.XSmall]) {
        ...
      } else if (result.breakpoints[Breakpoints.Small]) {
        ...
      } else if (result.breakpoints[Breakpoints.Medium]) {
        ...
      } else if (result.breakpoints[Breakpoints.Large]) {
        ...
      }
    });
  }
}

ThemeService

Dynamically change between your defined themes.

import { ThemeService } from '@lukfel/scaffold';

export class AppComponent {

  constructor(private themeService: ThemeService) {
    this.themeService.setTheme('my-theme2', true);    // the second parameter allows to persists the theme in the LocalStorage (using the built in LocalStorageService)
  }
}

Interceptors

Intercept HTTP Calls and automatically show a loading spinner.

  • Note: The loading spinner can also be manually shown by udpating the value for scaffoldConfig.loading in the ScaffoldService
import { ScaffoldModule } from '@lukfel/scaffold';
import { isDevMode } from '@angular/core';

@NgModule({
  ...
  imports: [
    ScaffoldModule.forRoot({ production: !isDevMode(), debugging: isDevMode() }),    // Omit .forRoot(...) if logging is not required
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: LoadingInterceptor,
      multi: true
    }
  ]
})
export class AppModule { }
19.0.1

8 months ago

19.0.3

8 months ago

19.0.2

8 months ago

18.0.5

8 months ago

19.1.11

5 months ago

19.1.10

5 months ago

19.0.5

8 months ago

18.0.4

8 months ago

19.0.4

8 months ago

19.0.7

8 months ago

19.0.6

8 months ago

19.0.9

8 months ago

19.0.8

8 months ago

19.0.17

7 months ago

19.0.16

7 months ago

19.0.15

7 months ago

19.0.10

8 months ago

19.0.14

7 months ago

19.0.13

7 months ago

19.0.12

8 months ago

19.0.11

8 months ago

19.1.2

7 months ago

19.1.1

7 months ago

19.1.4

7 months ago

19.1.3

7 months ago

19.1.6

7 months ago

19.1.5

7 months ago

19.1.8

5 months ago

19.1.7

7 months ago

19.1.9

5 months ago

17.0.9

1 year ago

17.0.7

1 year ago

17.0.8

1 year ago

17.0.6

1 year ago

17.0.3

1 year ago

17.0.5

1 year ago

17.0.4

1 year ago

17.0.1

2 years ago

17.0.0

2 years ago

16.0.0

2 years ago

15.6.0

2 years ago

1.2.8

3 years ago

1.2.7

3 years ago

15.5.0

3 years ago

1.3.3

3 years ago

1.4.1

3 years ago

1.3.2

3 years ago

15.5.2

3 years ago

15.4.3

3 years ago

1.4.0

3 years ago

1.3.1

3 years ago

15.5.1

3 years ago

15.4.2

3 years ago

1.3.0

3 years ago

15.4.5

3 years ago

15.5.3

3 years ago

15.4.4

3 years ago

15.4.7

3 years ago

15.4.6

3 years ago

15.4.9

3 years ago

15.4.8

3 years ago

1.2.6

3 years ago

1.2.5

3 years ago

1.2.4

3 years ago

1.2.3

3 years ago

1.2.2

3 years ago

1.2.1

3 years ago

1.2.0

3 years ago

1.1.9

3 years ago

1.1.8

3 years ago

1.1.7

3 years ago

1.1.6

3 years ago

1.1.5

3 years ago

1.1.4

3 years ago

1.1.3

3 years ago

1.1.2

3 years ago

1.1.1

3 years ago

1.1.0

3 years ago

1.0.9

3 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.6

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago