19.1.11 • Published 10 months ago

@lukfel/scaffold v19.1.11

Weekly downloads
-
License
MIT
Repository
github
Last release
10 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

1 year ago

19.0.3

1 year ago

19.0.2

1 year ago

18.0.5

1 year ago

19.1.11

10 months ago

19.1.10

10 months ago

19.0.5

1 year ago

18.0.4

1 year ago

19.0.4

1 year ago

19.0.7

1 year ago

19.0.6

1 year ago

19.0.9

1 year ago

19.0.8

1 year ago

19.0.17

12 months ago

19.0.16

12 months ago

19.0.15

12 months ago

19.0.10

1 year ago

19.0.14

12 months ago

19.0.13

12 months ago

19.0.12

1 year ago

19.0.11

1 year ago

19.1.2

12 months ago

19.1.1

12 months ago

19.1.4

12 months ago

19.1.3

12 months ago

19.1.6

11 months ago

19.1.5

11 months ago

19.1.8

10 months ago

19.1.7

11 months ago

19.1.9

10 months ago

17.0.9

2 years ago

17.0.7

2 years ago

17.0.8

2 years ago

17.0.6

2 years ago

17.0.3

2 years ago

17.0.5

2 years ago

17.0.4

2 years ago

17.0.1

2 years ago

17.0.0

2 years ago

16.0.0

2 years ago

15.6.0

3 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