UNPKG

@compodoc/compodoc

Version:

The missing documentation tool for your Angular application

803 lines (662 loc) 30.2 kB
<!doctype html> <html class="no-js" lang=""> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>@compodoc/compodoc documentation</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="../images/favicon.ico"> <link rel="stylesheet" href="../styles/style.css"> <link rel="stylesheet" href="../styles/dark.css"> </head> <body> <script> // Blocking script to avoid flickering dark mode // Dark mode toggle button var useDark = window.matchMedia('(prefers-color-scheme: dark)'); var darkModeState = useDark.matches; var $darkModeToggleSwitchers = document.querySelectorAll('.dark-mode-switch input'); var $darkModeToggles = document.querySelectorAll('.dark-mode-switch'); var darkModeStateLocal = localStorage.getItem('compodoc_darkmode-state'); function checkToggle(check) { for (var i = 0; i < $darkModeToggleSwitchers.length; i++) { $darkModeToggleSwitchers[i].checked = check; } } function toggleDarkMode(state) { if (window.localStorage) { localStorage.setItem('compodoc_darkmode-state', state); } checkToggle(state); const hasClass = document.body.classList.contains('dark'); if (state) { for (var i = 0; i < $darkModeToggles.length; i++) { $darkModeToggles[i].classList.add('dark'); } if (!hasClass) { document.body.classList.add('dark'); } } else { for (var i = 0; i < $darkModeToggles.length; i++) { $darkModeToggles[i].classList.remove('dark'); } if (hasClass) { document.body.classList.remove('dark'); } } } useDark.addEventListener('change', function (evt) { toggleDarkMode(evt.matches); }); if (darkModeStateLocal) { darkModeState = darkModeStateLocal === 'true'; } toggleDarkMode(darkModeState); </script> <script> // --- Iframe navigation tracking for Template Playground --- function sendCurrentUrlToParent() { if (window.parent && window.parent !== window) { window.parent.postMessage({ type: 'compodoc-iframe-navigate', url: window.location.pathname + window.location.hash }, '*'); } } window.addEventListener('hashchange', sendCurrentUrlToParent, false); window.addEventListener('popstate', sendCurrentUrlToParent, false); window.addEventListener('DOMContentLoaded', sendCurrentUrlToParent, false); </script> <div class="navbar navbar-default navbar-fixed-top d-md-none p-0"> <div class="d-flex"> <a href="../" class="navbar-brand">@compodoc/compodoc documentation</a> <button type="button" class="btn btn-default btn-menu ion-ios-menu" id="btn-menu"></button> </div> </div> <div class="xs-menu menu" id="mobile-menu"> <div id="book-search-input" role="search"><input type="text" placeholder="Saisissez un texte"></div> <compodoc-menu></compodoc-menu> </div> <div class="container-fluid main"> <div class="row main"> <div class="d-none d-md-block menu"> <compodoc-menu mode="normal"></compodoc-menu> </div> <!-- START CONTENT --> <div class="content class"> <div class="content-data"> <ol class="breadcrumb"> <li class="breadcrumb-item">Classes</li> <li class="breadcrumb-item" >NavigationData</li> </ol> <ul class="nav nav-tabs" role="tablist"> <li class="nav-item"> <a href="#info" class="nav-link" class="nav-link active" role="tab" id="info-tab" data-bs-toggle="tab" data-link="info">Info</a> </li> <li class="nav-item"> <a href="#source" class="nav-link" role="tab" id="source-tab" data-bs-toggle="tab" data-link="source">Source</a> </li> </ul> <div class="tab-content"> <div class="tab-pane fade active in" id="info"> <p class="comment"> <h3>Fichier</h3> </p> <p class="comment"> <code>test/fixtures/sample-files/query-param-group.service.ts</code> </p> <section data-compodoc="block-index"> <h3 id="index">Index</h3> <table class="table table-sm table-bordered index-table"> <tbody> <tr> <td class="col-md-4"> <h6><b>Propriétés</b></h6> </td> </tr> <tr> <td class="col-md-4"> <ul class="index-list"> <li> <span class="modifier">Public</span> <a href="#params" >params</a> </li> <li> <span class="modifier">Public</span> <a href="#synthetic" >synthetic</a> </li> </ul> </td> </tr> </tbody> </table> </section> <section data-compodoc="block-constructor"> <h3 id="constructor">Constructeur</h3> <table class="table table-sm table-bordered"> <tbody> <tr> <td class="col-md-4"> <code>constructor(params: Params, synthetic: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/boolean" target="_blank">boolean</a>)</code> </td> </tr> <tr> <td class="col-md-4"> <div class="io-line">Défini dans <a href="" data-line="52" class="link-to-prism">test/fixtures/sample-files/query-param-group.service.ts:52</a></div> </td> </tr> <tr> <td class="col-md-4"> <div> <b>Paramètres :</b> <table class="params"> <thead> <tr> <td>Nom</td> <td>Type</td> <td>Optionnel</td> </tr> </thead> <tbody> <tr> <td>params</td> <td> <code>Params</code> </td> <td> Non </td> </tr> <tr> <td>synthetic</td> <td> <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/boolean" target="_blank" >boolean</a></code> </td> <td> Non </td> </tr> </tbody> </table> </div> </td> </tr> </tbody> </table> </section> <section data-compodoc="block-properties"> <h3 id="inputs"> Propriétés </h3> <table class="table table-sm table-bordered"> <tbody> <tr> <td class="col-md-4"> <a name="params"></a> <span class="name"> <span class="modifier">Public</span> <span ><b>params</b></span> <a href="#params"><span class="icon ion-ios-link"></span></a> </span> </td> </tr> <tr> <td class="col-md-4"> <i>Type : </i> <code>Params</code> </td> </tr> <tr> <td class="col-md-4"> <div class="io-line">Défini dans <a href="" data-line="53" class="link-to-prism">test/fixtures/sample-files/query-param-group.service.ts:53</a></div> </td> </tr> </tbody> </table> <table class="table table-sm table-bordered"> <tbody> <tr> <td class="col-md-4"> <a name="synthetic"></a> <span class="name"> <span class="modifier">Public</span> <span ><b>synthetic</b></span> <a href="#synthetic"><span class="icon ion-ios-link"></span></a> </span> </td> </tr> <tr> <td class="col-md-4"> <i>Type : </i> <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/boolean" target="_blank" >boolean</a></code> </td> </tr> <tr> <td class="col-md-4"> <i>Valeur par défaut : </i><code>false</code> </td> </tr> <tr> <td class="col-md-4"> <div class="io-line">Défini dans <a href="" data-line="53" class="link-to-prism">test/fixtures/sample-files/query-param-group.service.ts:53</a></div> </td> </tr> </tbody> </table> </section> </div> <div class="tab-pane fade tab-source-code" id="source"> <pre class="line-numbers compodoc-sourcecode"><code class="language-typescript">import { Inject, Injectable, isDevMode, OnDestroy, Optional } from &#x27;@angular/core&#x27;; import { Params } from &#x27;@angular/router&#x27;; import { EMPTY, from, Observable, Subject } from &#x27;rxjs&#x27;; import { catchError, concatMap, debounceTime, distinctUntilChanged, filter, map, startWith, switchMap, takeUntil, tap } from &#x27;rxjs/operators&#x27;; import { compareParamMaps, filterParamMap, isMissing, isPresent, NOP } from &#x27;../util&#x27;; import { Unpack } from &#x27;../types&#x27;; import { QueryParamGroup } from &#x27;../model/query-param-group&#x27;; import { QueryParam } from &#x27;../model/query-param&#x27;; import { NGQP_ROUTER_ADAPTER, NGQP_ROUTER_OPTIONS, RouterAdapter, RouterOptions } from &#x27;../router-adapter/router-adapter.interface&#x27;; import { QueryParamAccessor } from &#x27;./query-param-accessor.interface&#x27;; /** @internal */ function isMultiQueryParam&lt;T&gt;( queryParam: QueryParam&lt;T&gt; | QueryParam&lt;T[]&gt; ): queryParam is QueryParam&lt;T[]&gt; { return queryParam.multi; } /** @internal */ function hasArrayValue&lt;T&gt;( queryParam: QueryParam&lt;T&gt; | QueryParam&lt;T[]&gt;, value: T | T[] ): value is T[] { return isMultiQueryParam(queryParam); } /** @internal */ function hasArraySerialization( queryParam: QueryParam&lt;any&gt;, values: string | string[] | null ): values is string[] { return isMultiQueryParam(queryParam); } /** @internal */ class NavigationData { constructor(public params: Params, public synthetic: boolean &#x3D; false) {} } /** * Service implementing the synchronization logic * * This service is the key to the synchronization process by binding a {@link QueryParamGroup} * to the router. * * @internal */ @Injectable() export class QueryParamGroupService implements OnDestroy { /** The {@link QueryParamGroup} to bind. */ private queryParamGroup: QueryParamGroup; /** List of {@link QueryParamAccessor} registered to this service. */ private directives &#x3D; new Map&lt;string, QueryParamAccessor[]&gt;(); /** * Queue of navigation parameters * * A queue is used for navigations as we need to make sure all parameter changes * are executed in sequence as otherwise navigations might overwrite each other. */ private queue$ &#x3D; new Subject&lt;NavigationData&gt;(); /** @ignore */ private synchronizeRouter$ &#x3D; new Subject&lt;void&gt;(); /** @ignore */ private destroy$ &#x3D; new Subject&lt;void&gt;(); constructor( @Inject(NGQP_ROUTER_ADAPTER) private routerAdapter: RouterAdapter, @Optional() @Inject(NGQP_ROUTER_OPTIONS) private globalRouterOptions: RouterOptions ) { this.setupNavigationQueue(); } /** @ignore */ public ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); this.synchronizeRouter$.complete(); if (this.queryParamGroup) { this.queryParamGroup._clearChangeFunctions(); } } /** * Uses the given {@link QueryParamGroup} for synchronization. */ public setQueryParamGroup(queryParamGroup: QueryParamGroup): void { // FIXME: If this is called when we already have a group, we probably need to do // some cleanup first. if (this.queryParamGroup) { throw new Error( &#x60;A QueryParamGroup has already been setup. Changing the group is currently not supported.&#x60; ); } this.queryParamGroup &#x3D; queryParamGroup; this.startSynchronization(); } /** * Registers a {@link QueryParamAccessor}. */ public registerQueryParamDirective(directive: QueryParamAccessor): void { // Capture the name here, particularly for the queue below to avoid re-evaluating // it as it might change over time. const queryParamName &#x3D; directive.name; const queryParam: QueryParam&lt;any&gt; &#x3D; this.queryParamGroup.get(queryParamName); if (!queryParam) { throw new Error( &#x60;Could not find query param with name ${queryParamName}. Did you forget to add it to your QueryParamGroup?&#x60; ); } if (!directive.valueAccessor) { throw new Error( &#x60;No value accessor found for the form control. Please make sure to implement ControlValueAccessor on this component.&#x60; ); } // Chances are that we read the initial route before a directive has been registered here. // The value in the model will be correct, but we need to sync it to the view once initially. directive.valueAccessor.writeValue(queryParam.value); // Proxy updates from the view to debounce them (if needed). const debouncedQueue$ &#x3D; new Subject&lt;any&gt;(); debouncedQueue$ .pipe( // Do not synchronize while the param is detached from the group filter(() &#x3D;&gt; !!this.queryParamGroup.get(queryParamName)), isPresent(queryParam.debounceTime) ? debounceTime(queryParam.debounceTime) : tap(), map((newValue: any) &#x3D;&gt; this.getParamsForValue(queryParam, newValue)), takeUntil(this.destroy$) ) .subscribe(params &#x3D;&gt; this.enqueueNavigation(new NavigationData(params))); directive.valueAccessor.registerOnChange((newValue: any) &#x3D;&gt; debouncedQueue$.next(newValue)); this.directives.set(queryParamName, [ ...(this.directives.get(queryParamName) || []), directive ]); } /** * Deregisters a {@link QueryParamAccessor} by referencing its name. */ public deregisterQueryParamDirective(queryParamName: string): void { if (!queryParamName) { return; } const directives &#x3D; this.directives.get(queryParamName); if (!directives) { return; } directives.forEach(directive &#x3D;&gt; { directive.valueAccessor.registerOnChange(NOP); directive.valueAccessor.registerOnTouched(NOP); }); this.directives.delete(queryParamName); const queryParam: QueryParam&lt;any&gt; &#x3D; this.queryParamGroup.get(queryParamName); if (queryParam) { queryParam._clearChangeFunctions(); } } private startSynchronization() { this.setupGroupChangeListener(); this.setupParamChangeListeners(); this.setupRouterListener(); this.watchNewParams(); } /** Listens for programmatic changes on group level and synchronizes to the router. */ private setupGroupChangeListener(): void { this.queryParamGroup._registerOnChange((newValue: Record&lt;string, any&gt;) &#x3D;&gt; { let params: Params &#x3D; {}; Object.keys(newValue).forEach(queryParamName &#x3D;&gt; { const queryParam: QueryParam&lt;any&gt; &#x3D; this.queryParamGroup.get(queryParamName); if (isMissing(queryParam)) { return; } params &#x3D; { ...params, ...this.getParamsForValue(queryParam, newValue[queryParamName]) }; }); this.enqueueNavigation(new NavigationData(params, true)); }); } /** Listens for programmatic changes on parameter level and synchronizes to the router. */ private setupParamChangeListeners(): void { Object.keys(this.queryParamGroup.queryParams).forEach(queryParamName &#x3D;&gt; this.setupParamChangeListener(queryParamName) ); } private setupParamChangeListener(queryParamName: string): void { const queryParam: QueryParam&lt;any&gt; &#x3D; this.queryParamGroup.get(queryParamName); if (!queryParam) { throw new Error(&#x60;No param in group found for name ${queryParamName}&#x60;); } queryParam._registerOnChange((newValue: any) &#x3D;&gt; this.enqueueNavigation( new NavigationData(this.getParamsForValue(queryParam, newValue), true) ) ); } /** Listens for changes in the router and synchronizes to the model. */ private setupRouterListener(): void { this.synchronizeRouter$ .pipe( startWith(undefined), switchMap(() &#x3D;&gt; this.routerAdapter.queryParamMap.pipe( // We want to ignore changes to query parameters which aren&#x27;t related to this // particular group; however, we do need to react if one of our parameters has // vanished when it was set before. distinctUntilChanged((previousMap, currentMap) &#x3D;&gt; { const keys &#x3D; Object.values(this.queryParamGroup.queryParams).map( queryParam &#x3D;&gt; queryParam.urlParam ); // It is important that we filter the maps only here so that both are filtered // with the same set of keys; otherwise, e.g. removing a parameter from the group // would interfere. return compareParamMaps( filterParamMap(previousMap, keys), filterParamMap(currentMap, keys) ); }) ) ), takeUntil(this.destroy$) ) .subscribe(queryParamMap &#x3D;&gt; { const synthetic &#x3D; this.isSyntheticNavigation(); const groupValue: Record&lt;string, any&gt; &#x3D; {}; Object.keys(this.queryParamGroup.queryParams).forEach(queryParamName &#x3D;&gt; { const queryParam: QueryParam&lt;any&gt; &#x3D; this.queryParamGroup.get(queryParamName); const newValue &#x3D; queryParam.multi ? this.deserialize(queryParam, queryParamMap.getAll(queryParam.urlParam)) : this.deserialize(queryParam, queryParamMap.get(queryParam.urlParam)); const directives &#x3D; this.directives.get(queryParamName); if (directives) { directives.forEach(directive &#x3D;&gt; directive.valueAccessor.writeValue(newValue) ); } groupValue[queryParamName] &#x3D; newValue; }); this.queryParamGroup.setValue(groupValue, { emitEvent: !synthetic, emitModelToViewChange: false }); }); } /** Listens for newly added parameters and starts synchronization for them. */ private watchNewParams(): void { this.queryParamGroup.queryParamAdded$ .pipe(takeUntil(this.destroy$)) .subscribe(queryParamName &#x3D;&gt; { this.setupParamChangeListener(queryParamName); this.synchronizeRouter$.next(); }); } /** Returns true if the current navigation is synthetic. */ private isSyntheticNavigation(): boolean { const navigation &#x3D; this.routerAdapter.getCurrentNavigation(); if (!navigation || navigation.trigger !&#x3D;&#x3D; &#x27;imperative&#x27;) { // When using the back / forward buttons, the state is passed along with it, even though // for us it&#x27;s now a navigation initiated by the user. Therefore, a navigation can only // be synthetic if it has been triggered imperatively. // See https://github.com/angular/angular/issues/28108. return false; } return navigation.extras &amp;&amp; navigation.extras.state &amp;&amp; navigation.extras.state[&#x27;synthetic&#x27;]; } /** Subscribes to the parameter queue and executes navigations in sequence. */ private setupNavigationQueue() { this.queue$ .pipe( takeUntil(this.destroy$), concatMap(data &#x3D;&gt; this.navigateSafely(data)) ) .subscribe(); } private navigateSafely(data: NavigationData): Observable&lt;any&gt; { return from( this.routerAdapter.navigate(data.params, { ...this.routerOptions, state: { synthetic: data.synthetic } }) ).pipe( catchError((err: any) &#x3D;&gt; { if (isDevMode()) { console.error(&#x60;There was an error while navigating&#x60;, err); } return EMPTY; }) ); } /** Sends a change of parameters to the queue. */ private enqueueNavigation(data: NavigationData): void { this.queue$.next(data); } /** * Returns the full set of parameters given a value for a parameter model. * * This consists mainly of properly serializing the model value and ensuring to take * side effect changes into account that may have been configured. */ private getParamsForValue&lt;T&gt;(queryParam: QueryParam&lt;any&gt;, value: T | undefined | null): Params { const newValue &#x3D; this.serialize(queryParam, value); const combinedParams: Params &#x3D; isMissing(queryParam.combineWith) ? {} : queryParam.combineWith(value); // Note that we list the side-effect parameters first so that our actual parameter can&#x27;t be // overridden by it. return { ...(combinedParams || {}), [queryParam.urlParam]: newValue }; } private serialize&lt;T&gt;(queryParam: QueryParam&lt;any&gt;, value: T): string | string[] { if (hasArrayValue(queryParam, value)) { return (value || []).map(queryParam.serialize); } else { return queryParam.serialize(value); } } private deserialize&lt;T&gt;( queryParam: QueryParam&lt;T&gt;, values: string | string[] ): Unpack&lt;T&gt; | Unpack&lt;T&gt;[] { if (hasArraySerialization(queryParam, values)) { return values.map(queryParam.deserialize); } else { return queryParam.deserialize(values); } } /** * Returns the current set of options to pass to the router. * * This merges the global configuration with the group specific configuration. */ private get routerOptions(): RouterOptions { const groupOptions &#x3D; this.queryParamGroup ? this.queryParamGroup.routerOptions : {}; return { ...(this.globalRouterOptions || {}), ...groupOptions }; } } </code></pre> </div> </div> </div><div class="search-results"> <div class="has-results"> <h1 class="search-results-title"><span class='search-results-count'></span> résultats matchant "<span class='search-query'></span>"</h1> <ul class="search-results-list"></ul> </div> <div class="no-results"> <h1 class="search-results-title">Aucun résultat matchant "<span class='search-query'></span>"</h1> </div> </div> </div> <!-- END CONTENT --> </div> </div> <label class="dark-mode-switch"> <input type="checkbox"> <span class="slider"> <svg class="slider-icon" viewBox="0 0 24 24" fill="none" height="20" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" width="20" xmlns="http://www.w3.org/2000/svg"> <path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"></path> </svg> </span> </label> <script> var COMPODOC_CURRENT_PAGE_DEPTH = 1; var COMPODOC_CURRENT_PAGE_CONTEXT = 'class'; var COMPODOC_CURRENT_PAGE_URL = 'NavigationData.html'; var MAX_SEARCH_RESULTS = 15; </script> <script> $darkModeToggleSwitchers = document.querySelectorAll('.dark-mode-switch input'); checkToggle(darkModeState); if ($darkModeToggleSwitchers.length > 0) { for (var i = 0; i < $darkModeToggleSwitchers.length; i++) { $darkModeToggleSwitchers[i].addEventListener('change', function (event) { darkModeState = !darkModeState; toggleDarkMode(darkModeState); }); } } </script> <script src="../js/libs/custom-elements.min.js"></script> <script src="../js/libs/lit-html.js"></script> <script src="../js/menu-wc.js" defer></script> <script nomodule src="../js/menu-wc_es5.js" defer></script> <script src="../js/libs/bootstrap-native.js"></script> <script src="../js/libs/es6-shim.min.js"></script> <script src="../js/libs/EventDispatcher.js"></script> <script src="../js/libs/promise.min.js"></script> <script src="../js/compodoc.js"></script> <script src="../js/tabs.js"></script> <script src="../js/menu.js"></script> <script src="../js/libs/clipboard.min.js"></script> <script src="../js/libs/prism.js"></script> <script src="../js/sourceCode.js"></script> <script src="../js/search/search.js"></script> <script src="../js/search/lunr.min.js"></script> <script src="../js/search/search-lunr.js"></script> <script src="../js/search/search_index.js"></script> <script src="../js/lazy-load-graphs.js"></script> </body> </html>