File

src/modules/progress-indicator/directives/progress-indicator.directive.ts

Description

This directive must be used as attribute on a DOM element and the config provided should be a StarkProgressIndicatorConfig object:

Example :
<some-element [starkProgressIndicator]="{topic: 'some-topic', type: 'SPINNER'}" ></some-element>
<!-- or -->
<some-element [starkProgressIndicator]="progressIndicatorConfig" ></some-element>

Once the directive is initialized, it registers itself to the StarkProgressIndicatorService and creates an instance of the StarkProgressIndicatorComponent which is the one that actually displays the progress indicator (e.g., spinner).

From then on you can control the state/visibility of the progress indicator programmatically by using the StarkProgressIndicatorService:

Example :
// the service should be injected in your component
@Inject(STARK_PROGRESS_INDICATOR_SERVICE) private progressService: StarkProgressIndicatorService;

// then you can call the method to show the progress indicator
this.progressService.show(this.progressIndicatorConfig.topic);
// or to hide it
this.progressService.hide(this.progressIndicatorConfig.topic);

Implements

OnInit OnDestroy

Metadata

Index

Properties
Methods
Inputs

Constructor

Public constructor(_progressService: StarkProgressIndicatorService, componentFactoryResolver: ComponentFactoryResolver, injector: Injector, _viewContainer: ViewContainerRef, renderer: Renderer2, elementRef: ElementRef)

Class constructor

Parameters :
Name Type Optional Description
_progressService StarkProgressIndicatorService No
  • The ProgressIndicator service of the application
componentFactoryResolver ComponentFactoryResolver No
  • Resolver that returns Angular component factories
injector Injector No
  • The application Injector
_viewContainer ViewContainerRef No
  • The container where one or more views can be attached to the host element of this directive.
renderer Renderer2 No
  • Angular Renderer2 wrapper for DOM manipulations.
elementRef ElementRef No
  • Reference to the DOM element where this directive is applied to.

Inputs

starkProgressIndicator
Type : StarkProgressIndicatorConfig

Configuration object for the progress indicator to be shown.

Methods

Public ngOnDestroy
ngOnDestroy()

The directive de-registers itself from the StarkProgressIndicatorService when it is destroyed.

Returns : void
Public ngOnInit
ngOnInit()

The directive registers itself to the StarkProgressIndicatorService. The component to add is then created and inserted inside of the container. Finally, if the host component should be hidden or shown, the "stark-hide" class is removed/added accordingly

Returns : void
Public registerInstance
registerInstance(progressConfig: StarkProgressIndicatorConfig)

Registers an instance of progress indicator

Parameters :
Name Type Optional Description
progressConfig StarkProgressIndicatorConfig No
  • StarkProgressIndicatorConfig object
Returns : void

Properties

Public _progressService
Type : StarkProgressIndicatorService
Decorators :
@Inject(STARK_PROGRESS_INDICATOR_SERVICE)
- The ProgressIndicator service of the application
Public topic
Type : string

The topic that the progress indicator will subscribe to.

Public type
Type : StarkProgressIndicatorType | string

Type of progress indicator

import {
	ComponentFactoryResolver,
	Directive,
	ElementRef,
	Inject,
	Injector,
	Input,
	OnDestroy,
	OnInit,
	Renderer2,
	ViewContainerRef,
	ViewRef
} from "@angular/core";
import { STARK_PROGRESS_INDICATOR_SERVICE, StarkProgressIndicatorService } from "../services";
import { StarkProgressIndicatorConfig, StarkProgressIndicatorType } from "../entities";
import { Subscription } from "rxjs";
import { StarkProgressIndicatorComponent } from "../components";

/**
 * @ignore
 */
const directiveName = "[starkProgressIndicator]";

/* eslint-disable jsdoc/check-alignment,jsdoc/check-indentation */
/**
 * This directive must be used as attribute on a DOM element and the config provided should be a {@link StarkProgressIndicatorConfig} object:
 *
```html
<some-element [starkProgressIndicator]="{topic: 'some-topic', type: 'SPINNER'}" ></some-element>
<!-- or -->
<some-element [starkProgressIndicator]="progressIndicatorConfig" ></some-element>
```
 *
 * Once the directive is initialized, it registers itself to the {@link StarkProgressIndicatorService} and creates an instance of the {@link StarkProgressIndicatorComponent} which is the one that actually displays the progress indicator (e.g., spinner).
 *
 * From then on you can control the state/visibility of the progress indicator programmatically by using the {@link StarkProgressIndicatorService}:
 *
```typescript
// the service should be injected in your component
@Inject(STARK_PROGRESS_INDICATOR_SERVICE) private progressService: StarkProgressIndicatorService;

// then you can call the method to show the progress indicator
this.progressService.show(this.progressIndicatorConfig.topic);
// or to hide it
this.progressService.hide(this.progressIndicatorConfig.topic);
```
 */
/* eslint-enable jsdoc/check-alignment,jsdoc/check-indentation */
@Directive({
	selector: directiveName
})
export class StarkProgressIndicatorDirective implements OnInit, OnDestroy {
	/**
	 * Configuration object for the progress indicator to be shown.
	 */
	@Input()
	public starkProgressIndicator!: StarkProgressIndicatorConfig;

	/**
	 * The topic that the progress indicator will subscribe to.
	 */
	public topic!: string;

	/**
	 * Type of progress indicator
	 */
	public type!: StarkProgressIndicatorType | string;

	/**
	 * @ignore
	 */
	private progressSubscription?: Subscription;

	/**
	 * @ignore
	 */
	private readonly componentViewRef!: ViewRef;

	/**
	 * Class constructor
	 * @param _progressService - The ProgressIndicator service of the application
	 * @param componentFactoryResolver - Resolver that returns Angular component factories
	 * @param injector - The application Injector
	 * @param _viewContainer - The container where one or more views can be attached to the host element of this directive.
	 * @param renderer - Angular `Renderer2` wrapper for DOM manipulations.
	 * @param elementRef - Reference to the DOM element where this directive is applied to.
	 */
	public constructor(
		@Inject(STARK_PROGRESS_INDICATOR_SERVICE) public _progressService: StarkProgressIndicatorService,
		componentFactoryResolver: ComponentFactoryResolver,
		injector: Injector,
		private _viewContainer: ViewContainerRef,
		protected renderer: Renderer2,
		protected elementRef: ElementRef
	) {
		const componentFactory = componentFactoryResolver.resolveComponentFactory(StarkProgressIndicatorComponent);
		const componentRef = componentFactory.create(injector);
		this.componentViewRef = componentRef.hostView;
	}

	/**
	 * Registers an instance of progress indicator
	 * @param progressConfig - `StarkProgressIndicatorConfig` object
	 */
	public registerInstance(progressConfig: StarkProgressIndicatorConfig): void {
		this.topic = progressConfig.topic;

		if (typeof StarkProgressIndicatorType[progressConfig.type] !== "undefined") {
			this.type = StarkProgressIndicatorType[progressConfig.type];
		} else {
			this.type = StarkProgressIndicatorType.SPINNER;
		}

		this._progressService.register(this.topic, <StarkProgressIndicatorType>this.type);
	}

	/**
	 * The directive registers itself to the {@link StarkProgressIndicatorService}.
	 * The component to add is then created and inserted inside of the container.
	 * Finally, if the host component should be hidden or shown, the "stark-hide" class is removed/added accordingly
	 */
	public ngOnInit(): void {
		if (!this.starkProgressIndicator) {
			throw new Error("StarkProgressIndicatorDirective: a StarkProgressIndicatorConfig is required.");
		}
		this.registerInstance(this.starkProgressIndicator);

		this.progressSubscription = this._progressService.isVisible(this.topic).subscribe((isVisible: boolean = false) => {
			if (isVisible) {
				// TODO The element is here added as a child, not as a sibling
				// this.renderer.appendChild(this.elementRef.nativeElement, componentRef.location.nativeElement);

				this._viewContainer.insert(this.componentViewRef); // insert the view in the last position
				this.renderer.addClass(this.elementRef.nativeElement, "stark-hide");
			} else {
				const componentViewRefIndex = this._viewContainer.indexOf(this.componentViewRef);
				if (componentViewRefIndex > -1) {
					this._viewContainer.detach(componentViewRefIndex);
					this.renderer.removeClass(this.elementRef.nativeElement, "stark-hide");
				}
			}
		});
	}

	/**
	 * The directive de-registers itself from the {@link StarkProgressIndicatorService} when it is destroyed.
	 */
	public ngOnDestroy(): void {
		this.componentViewRef.destroy(); // destroy the progress indicator
		if (this.progressSubscription) {
			this.progressSubscription.unsubscribe();
		}
		this._progressService.deregister(this.topic);
	}
}

results matching ""

    No results matching ""