Right now I am developing an Angular Application that is based on a library that will contain all UI-Elements used in multiple projects.

As you can imagine, it can be difficult for different teams to use the same base of UI-Elements without a good documentation of how things work.

Therefore I have tried multiple tools like compodoc that generate API Docs from an Angular app/library. But since none of them were exactly what I was looking for, I searched for other ways to simply show the code of an example as well as the example itself rendered — and all that WITHOUT code duplication.

Since I am now writing this article you can assume, that I have found a way 😉.

So first let me show you the result of what I achieved.

Image for post

Result in action


The idea

I wanted to write the code for examples only ONCE and the component should update the code-snippet and the example-view without further need of modification.

The code-snippet should be visually appealing to the user and use syntax highlighting and right indentation.


How to

Let’s jump right into the code.

Let me start with the component wrapping most of this logic:

import { AfterContentInit, Component, Input } from "@angular/core";
	import "code-prettify/loader/run_prettify";
	import { sleep } from "../helpers";

	declare const window: Window & { PR: any };

	@Component({
	    selector: "app-example-view",
	    template: `
	        <h2>{{exampleTitle}}</h2>
	        <ui-tab-group selectedTabKey="example" class="tabGroup">
	            <ui-tab key="example" label="Example">
	                <div example class="contentWrapper">
	                    <ng-content></ng-content>
	                </div>
	            </ui-tab>
	            <ui-tab key="code" label="Code" (onSelect)="prettyPrint()">
	                <pre class="prettyprint" code [ngClass]="'lang-' + lang" [innerText]="code"></pre>
	            </ui-tab>
	            <ui-tab key="api" label="API">
	                <app-doc-view *ngIf="components" [components]="components"></app-doc-view>
	            </ui-tab>
	        </ui-tab-group>
	    `,
	    styles: [`
	        :host {
	            display: flex;
	            flex-direction: column;
	            padding: 8px;
	            height: auto;
	        }
	        pre {
	            margin: 10px 0;
	            border: 1px solid #666;
	            border-radius: 4px;
	            overflow: auto;
	            padding: 8px;
	        }
	        .contentWrapper {
	            padding: 10px 0;
	        }
	        .tabGroup {
	            padding: 10px 0;
	        }
	    `]
	})
	export class ExampleViewComponent implements AfterContentInit {

	    /**
	     * The title of the example snippet.
	     */
	    @Input()
	    public exampleTitle = "";

	    /**
	     * The code to show as an example.
	     */
	    @Input()
	    public code = "";

	    /**
	     * The name of the component to show an example for.
	     */
	    @Input()
	    public components: Array<string> | undefined;

	    /**
	     * The language of the code.
	     * Preset is HTML.
	     */
	    @Input()
	    public lang: "HTML" | "js" = "HTML";

	    /**
	     * Array the tabs to be shown.
	     */
	    @Input()
	    public tabsToShow: Array<string> = ["example", "code"];

	    /**
	     * PrettyPrints as soon as the content is initialized and adds the api tab if needed.
	     */
	    public async ngAfterContentInit(): Promise<void> {
	        if (this.components && this.components.length > 0 && !this.tabsToShow.includes("api")) {
	            this.tabsToShow.push("api");
	        }
	        await this.prettyPrint();
	    }

	    /**
	     * Pretty prints the example text again.
	     */
	    public async prettyPrint(): Promise<void> {
	        await sleep();
	        window.PR?.prettyPrint();
	    }
	}

#documentation #angular #typescript #team-collaboration #libraries

Want a More Usable Angular Library?
1.45 GEEK