UNPKG

@rxap/form-system

Version:

This package provides a set of directives, decorators, mixins, and validators to simplify the creation of dynamic forms in Angular applications. It offers features such as automatic control creation, data source integration, component customization, and h

358 lines (280 loc) 12.4 kB
<!doctype html> <html class="no-js" lang=""> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>angular-form-system</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> <div class="navbar navbar-default navbar-fixed-top d-md-none p-0"> <div class="d-flex"> <a href="../" class="navbar-brand">angular-form-system</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="Type to search"></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 interface"> <div class="content-data"> <ol class="breadcrumb"> <li class="breadcrumb-item">Interfaces</li> <li class="breadcrumb-item" > OptionsFromMethodDirectiveSettings</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>File</h3> </p> <p class="comment"> <code>src/lib/directives/options-from-method.directive.ts</code> </p> </div> <div class="tab-pane fade tab-source-code" id="source"> <pre class="line-numbers compodoc-sourcecode"><code class="language-typescript">import { AfterViewInit, ChangeDetectorRef, Directive, inject, InjectFlags, INJECTOR, Injector, Input, OnChanges, SimpleChanges, TemplateRef, ViewContainerRef, } from &#x27;@angular/core&#x27;; import { AbstractControlDirective, NgControl, } from &#x27;@angular/forms&#x27;; import { MatFormField } from &#x27;@angular/material/form-field&#x27;; import { RxapFormControl } from &#x27;@rxap/forms&#x27;; import { Mixin } from &#x27;@rxap/mixin&#x27;; import { Method } from &#x27;@rxap/pattern&#x27;; import { ControlOption, ControlOptions, } from &#x27;@rxap/utilities&#x27;; import { ExtractOptionsMethodMixin } from &#x27;../mixins/extract-options-method.mixin&#x27;; export interface OptionsFromMethodTemplateContext { $implicit: ControlOption; } // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface OptionsFromMethodDirectiveSettings { } // eslient-disable-next-line @typescript-eslint/no-empty-interface export interface OptionsFromMethodDirective&lt;Value &#x3D; any, Parameters &#x3D; any&gt; extends AfterViewInit, OnChanges, ExtractOptionsMethodMixin { } @Mixin(ExtractOptionsMethodMixin) @Directive({ // eslint-disable-next-line @angular-eslint/directive-selector selector: &#x27;[rxapOptionsFromMethod]&#x27;, standalone: true, }) export class OptionsFromMethodDirective&lt;Value &#x3D; any, Parameters &#x3D; any&gt; implements AfterViewInit, OnChanges { static ngTemplateContextGuard( dir: OptionsFromMethodDirective, ctx: any, ): ctx is OptionsFromMethodTemplateContext { return true; } @Input(&#x27;rxapOptionsFromMethodParameters&#x27;) public parameters?: Parameters; @Input(&#x27;rxapOptionsFromMethodResetOnChange&#x27;) public resetOnChange?: Value; public options: ControlOptions | null &#x3D; null; // eslint-disable-next-line @angular-eslint/no-input-rename @Input(&#x27;rxapOptionsFromMethodCall&#x27;) public method!: Method&lt;ControlOptions, Parameters&gt;; protected ngControl: NgControl | AbstractControlDirective | null &#x3D; null; protected matFormField: MatFormField | null &#x3D; null; protected settings: OptionsFromMethodDirectiveSettings &#x3D; {}; protected readonly viewContainerRef: ViewContainerRef &#x3D; inject(ViewContainerRef); protected readonly injector: Injector &#x3D; inject(INJECTOR); protected readonly cdr: ChangeDetectorRef &#x3D; inject(ChangeDetectorRef); private readonly template: TemplateRef&lt;OptionsFromMethodTemplateContext&gt; &#x3D; inject(TemplateRef); public async ngAfterViewInit() { this.matFormField &#x3D; this.injector.get(MatFormField, null); this.ngControl &#x3D; this.matFormField?._control.ngControl ?? this.injector.get(NgControl, null); this.control &#x3D; (this.ngControl?.control as RxapFormControl) ?? undefined; this.method ??&#x3D; this.extractOptionsMethod(); // ensure that the options are loaded. It is possible that the ngOnChange is triggered before the ngAfterViewInit // then the options are not loaded. if (!this.options) { this.setOptions(await this.loadOptions(this.parameters)); } } public async ngOnChanges(changes: SimpleChanges) { // only try to load the options if the method is defined // else the initial load will be triggered in the ngAfterViewInit if (!this.method) { console.debug(&#x27;The method is not yet defined&#x27;); return; } const parametersChanges &#x3D; changes[&#x27;parameters&#x27;]; if (parametersChanges) { this.setOptions(await this.loadOptions(parametersChanges.currentValue)); } } protected async loadOptions(parameters?: Parameters): Promise&lt;ControlOptions | null&gt; { return this.method.call(parameters); } protected renderTemplate() { if (!this.options) { throw new Error(&#x27;The options are not yet loaded&#x27;); } this.viewContainerRef.clear(); for (const option of this.options) { this.viewContainerRef.createEmbeddedView(this.template, {$implicit: option}); } if (this.resetOnChange !&#x3D;&#x3D; undefined) { this.control?.reset(this.resetOnChange); } this.cdr.detectChanges(); } protected setOptions(options: ControlOptions | null) { if (!options) { this.options &#x3D; null; this.viewContainerRef.clear(); } else { this.options &#x3D; options.slice(); this.renderTemplate(); } } } </code></pre> </div> </div> </div><div class="search-results"> <div class="has-results"> <h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1> <ul class="search-results-list"></ul> </div> <div class="no-results"> <h1 class="search-results-title">No results matching "<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 = 'interface'; var COMPODOC_CURRENT_PAGE_URL = 'OptionsFromMethodDirectiveSettings.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/libs/zepto.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>