{"id":2481,"date":"2019-04-10T12:11:37","date_gmt":"2019-04-10T10:11:37","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=2481"},"modified":"2019-04-10T12:11:37","modified_gmt":"2019-04-10T10:11:37","slug":"dynamic-forms-with-angular-2","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-forms-with-angular-2\/","title":{"rendered":"Dynamic Forms With Angular 2"},"content":{"rendered":"<div class=\"article\">\n<blockquote>\n<p>This post refers to the RC 1 of Angular 2 which was the current version when it was written. For the RC 2 some renamings are planned. An adoption to it seems to be possible via find\/replace. See the summary at the end of this <a href=\"https:\/\/docs.google.com\/document\/d\/1RIezQqE4aEhBRmArIAS1mRIZtWFf6JxN_7B4meyWK0Y\/pub\">design-document<\/a> for a list of this renamings.\n<\/p><\/blockquote>\n<p>To simplify dealing with many similar forms, you can make use of form generators. This approach gives also a server-side use-case-control the possibility to influence the presented forms.<\/p>\n<p>The imperative forms handling in Angular 2 makes it very easy to implement such a <a href=\"https:\/\/angular.io\/docs\/ts\/latest\/cookbook\/dynamic-form.html\">form generator<\/a>. Information about this can be found in the <a href=\"https:\/\/angular.io\/docs\/ts\/latest\/cookbook\/dynamic-form.html\">documentation of angular<\/a>. To make this approach more flexible, you can put the <a href=\"https:\/\/angular.io\/docs\/js\/latest\/api\/core\/DynamicComponentLoader-class.html\">\"DynamicComponentLoaders\"<\/a> into play. This allows a dynamic integration of components. Thus, an application can display controls, which are only mentioned in a form-description.<\/p>\n<p>This article describes such an implementation. It assumes that every dynamically loaded control implements the interface <code>ControlValueAccessor<\/code>, which allows it to play together with Angular's mechanismns for forms-handling. The <a href=\"https:\/\/github.com\/manfredsteyer\/angular2-rc1-forms\">entire example<\/a> can be found <a href=\"https:\/\/github.com\/manfredsteyer\/angular2-rc1-forms\">here<\/a>.<\/p>\n<h1>Metadata for dynamic form<\/h1>\n<p>To generate a form using the approach described here, a component offers metadata for a form. For the sake of simplification, this metadata consists of two parts, namely a <code>ControlGroup<\/code> used by the imperative forms handling and an array of <code>elements<\/code> which contains additional data for the form-controls. It then stows these two pieces of information in an object with the name <code>formMetaData<\/code>:<\/p>\n<pre><code>@Component({\n    selector: 'flight-search',  \n    template: require('.\/flight-search.component.html'),\n    directives: [DynamicFormComponent]\n})\nexport class FlightSearchImpComponent {\n\n    public filter: ControlGroup;\n    public formMetaData;\n\n    constructor(\n        private flugService: FlugService,\n        private fb: FormBuilder) {\n\n            this.filter = fb.group({\n               from: [\n                    'Graz',\n                    Validators.compose([\n                        Validators.required, \n                        Validators.minLength(3),\n                        Validators.maxLength(50),\n                        OrtValidator.validateWithParams(['Graz', 'Wien', 'Hamburg']),\n                        Validators.pattern(\"[a-zA-Z0-9]+\")\n                    ]),\n                    Validators.composeAsync([\n                        OrtAsyncValidator.validateAsync\n                    ])\n               ],\n               to: ['Hamburg'],\n               date: ['2016-05-01']\n            });\n\n            var elements = [\n                { fieldName: 'from', label: 'From' },\n                { fieldName: 'to', label: 'To' },\n                { fieldName: 'date', label: 'Datum', controlName: 'date-control' }\n            ];\n\n            this.formMetaData = {\n                controlGroup: this.filter,\n                elements: elements  \n            };\n    }\n\n    [...]\n}\n\n<\/code><\/pre>\n<p>To define a control for a field, the component uses the property <code>controlName<\/code>. On this way, the considered example configures the usage of the component <code>date-control<\/code> for the property <code>date<\/code>.<\/p>\n<p>This metadata is passed to the <code>dynamic-form<\/code> component. The implementation of this component can be found in the next section.<\/p>\n<pre><code>&lt;dynamic-form [formMetaData]=\"formMetaData\"&gt;\n&lt;\/dynamic-form&gt;  \n<\/code><\/pre>\n<h2>DynamicForm-Component<\/h2>\n<p>The component <code>dynamic-form<\/code> takes the passed metadata and uses it within it's template to render the form in question:<\/p>\n<pre><code>import { Component, Input } from '@angular\/core';\n\n@Component({\n    selector: 'dynamic-form',\n    template: require('.\/dynamic-form.component.html')    \n})\nexport class DynamicFormComponent {\n\n    @Input() formMetaData;\n\n}\n<\/code><\/pre>\n<p>The form is bound to the <code>ControlGroup<\/code> using <code>ngFormModel<\/code> and the array <code>elements<\/code> is iterated. For each array-entry the sample renders a control which is bound to a <code>Control<\/code> within the mentioned <code>ControlGroup<\/code>. For this, the Attribute <code>ngControl<\/code> gets the name of the <code>Control<\/code> in question. <\/p>\n<p>By default, it uses an ordinary <code>input<\/code>-element, but when there is a property <code>controlName<\/code> with the value <code>date-control<\/code>, it renders a <code>date-control<\/code>. This is a simple control that can be used to edit date-values. The <a href=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/admin\/editor\/post.cshtml?id=f485a00d-8a77-44f4-8f66-a3fa467ca1d4\">implementation<\/a> of it is described here. <\/p>\n<pre><code>&lt;form [ngFormModel]=\"formMetaData.controlGroup\"&gt;\n\n    &lt;h2&gt;Form Generator with dynamic Components&lt;\/h2&gt;\n\n    &lt;div *ngFor=\"let entry of formMetaData.elements\" class=\"form-group\"&gt;\n\n        &lt;div *ngIf=\"!entry.controlName &amp;&amp; !entry.control\"&gt;\n            &lt;label&gt;{{entry.label}}&lt;\/label&gt;\n            &lt;input [ngControl]=\"entry.fieldName\" class=\"form-control\"&gt;\n        &lt;\/div&gt;\n\n        &lt;!-- Issue: Template has to know all Controls here --&gt;\n        &lt;div *ngIf=\"entry.controlName == 'date-control'\"&gt;\n            &lt;label&gt;{{entry.label}}&lt;\/label&gt;\n            &lt;date-control [ngControl]=\"entry.fieldName\"&gt;&lt;\/date-control&gt;\n        &lt;\/div&gt;\n\n    &lt;\/div&gt;\n\n    &lt;ng-content&gt;&lt;\/ng-content&gt;\n\n&lt;\/form&gt;\n\n<\/code><\/pre>\n<p>This approach works quite well, but has the disadvantage that the <code>DynamicFormComponent<\/code> must know all controls and respect them with an own branch. To lower this strong coupling, the following extensions use the possibility to load controls dynamically into the page.<\/p>\n<h1>Dynamically load controls<\/h1>\n<p>To enable loading components dynamically, the affected entry in the array <code>elements<\/code> gets a direct reference to the component-controller, which is just a class. An application could also dynamically fetch this control-controller from the server at run time, e. g. by using <code>System.import<\/code>.<\/p>\n<pre><code>var elements = [\n    { fieldName: 'from', label: 'From' },\n    { fieldName: 'to', label: 'To' },\n    { fieldName: 'date', label: 'Datum', control: DateControlComponent }\n    \/\/                                              ^\n    \/\/                                              |\n    \/\/                  Component to use -----------+\n];\n<\/code><\/pre>\n<p>The below presented component <code>ControlWrapperComponent<\/code> takes care of dynamic loading in this scenario. As its name suggests, it is a wrapper for the component which is to be loaded dynamically. It implements the lifecycle-hook <code>OnInit<\/code> and the <code>ControlValueAccessor<\/code> interface. The latter is necessary, to make it with work with Angular's forms handling. It takes the necessary metadata from the <code>input<\/code>-binding <code>metadata<\/code>.<\/p>\n<p>In addition, it has properties for the dynamically loaded components (<code>innerComponent<\/code>), the ChangeDetector of this component (<code>innerComponentChangeDetectorRef<\/code>) and the current value (<code>value<\/code>). As described in <a href=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/admin\/editor\/post.cshtml?id=f485a00d-8a77-44f4-8f66-a3fa467ca1d4\">this example<\/a>, the constructor sets up the component as its own <code>ValueAccessor<\/code>.<\/p>\n<p>The method <code>writeValue<\/code> is called by Angular to set the current value. If the dynamically loaded component already exists, it passes this value to it and then it triggers the <code>ChangeDetector<\/code> to update its view.<\/p>\n<p>The methods <code>registerOnChange<\/code> and <code>registerOnTouched<\/code> take callbacks from Angular and stow them within the member-variables <code>onChange<\/code> and <code>onTouched<\/code>. With these callbacks the component informs Angular when the user changes the displayed value.<\/p>\n<p>The lifecycle hook <code>ngOnInit<\/code> uses the injected <code>DynamicComponentLoader<\/code> to load the desired component. It's method <code>loadAsRoot<\/code> takes the reference to the component class, a CSS selector and an injector. The CSS selector determines where to place the component within the template. The injector determines what services the component can get via dependency injection. In the considered case the injector of the wrapper-component is used for this purpose.<\/p>\n<p>After loading the component, the generated component-instance as well as it's <code>ChangeDetector<\/code> is put into variables. Then <code>ngOnInit<\/code> passes the current value (<code>value<\/code>) to the newly created component via <code>writeValue<\/code>. After that, it triggers it's <code>ChangeDetector<\/code>.<\/p>\n<p>Then, the wrapper component registeres callbacks to keep track of changes. To do this, it passes lambda expressions to <code>registerOnChanged<\/code> and <code>registerOnTouched<\/code>. These lambda expressions delegate to Angular by calling <code>onChange<\/code> and <code>onTouched<\/code>. <\/p>\n<pre><code>import { Component, Input, OnInit, DynamicComponentLoader, Injector, ChangeDetectorRef } from '@angular\/core';\nimport {ControlValueAccessor, NgControl } from '@angular\/common';\n\n@Component({\n    selector: 'control-wrapper',\n    template: '&lt;span id=\"control\"&gt;&lt;\/span&gt;'\n})\nexport class ControlWrapperComponent \n                    implements OnInit, ControlValueAccessor {\n\n    @Input() metadata;\n\n    innerComponent: any;\n    innerComponentChangeDetectorRef: ChangeDetectorRef;\n    value: any;\n\n    constructor(\n        private c: NgControl, \n        private dcl: DynamicComponentLoader, \n        private injector: Injector) {\n\n        c.valueAccessor = this;\n    }\n\n    writeValue(value: any) {\n        this.value = value;\n        if (this.innerComponent) {\n            this.innerComponent.writeValue(value);\n            this.innerComponentChangeDetectorRef.detectChanges();\n        }\n    }\n\n    onChange = (_) =&gt; {};\n    onTouched = () =&gt; {};\n    registerOnChange(fn): void { this.onChange = fn; }\n    registerOnTouched(fn): void { this.onTouched = fn; }\n\n    ngOnInit() {\n\n        this.dcl.loadAsRoot(this.metadata.control, '#control', this.injector)\n\n            .then(compRef =&gt; {\n                this.innerComponent                  = compRef.instance;\n                this.innerComponentChangeDetectorRef = compRef.changeDetectorRef;\n\n                this.innerComponent.writeValue(this.value);\n                compRef.changeDetectorRef.detectChanges();\n\n                this.innerComponent.registerOnChange((value) =&gt; {\n                    this.value = value;\n                    this.onChange(value); \n                });\n                this.innerComponent.registerOnTouched(() =&gt; {\n                    this.onTouched();\n                })\n\n            });\n    }\n\n}\n<\/code><\/pre>\n<h1>Dynamic-Form-Component um dynamische Steuerelemente erweitern<\/h1>\n<p>The <code>DynamicFormComponent<\/code> can now use the wrapper-component:<\/p>\n<pre><code>import { Component, Input } from '@angular\/core';\nimport { ControlWrapperComponent} from '..\/control-wrapper\/control-wrapper.component';\n\n@Component({\n    selector: 'dynamic-form',\n    template: require('.\/dynamic-form.component.html'),\n    directives: [ControlWrapperComponent]    \n})\nexport class DynamicFormComponent {\n\n    @Input() formMetaData;\n\n}\n<\/code><\/pre>\n<p>In addition, the template uses the wrapper-component for each field that refers to a component by the means of the property <code>control<\/code>. This contains the metadata including the control to dynamically load.<\/p>\n<pre><code>&lt;form [ngFormModel]=\"formMetaData.controlGroup\"&gt;\n\n    &lt;h2&gt;Form Generator with dynamic Components&lt;\/h2&gt;\n\n    &lt;div *ngFor=\"let entry of formMetaData.elements\" class=\"form-group\"&gt;\n\n        &lt;div *ngIf=\"!entry.controlName &amp;&amp; !entry.control\"&gt;\n            &lt;label&gt;{{entry.label}}&lt;\/label&gt;\n            &lt;input [ngControl]=\"entry.fieldName\" class=\"form-control\"&gt;\n        &lt;\/div&gt;\n\n        &lt;div *ngIf=\"entry.control\"&gt;\n            &lt;label&gt;{{entry.label}}&lt;\/label&gt;\n            &lt;control-wrapper [metadata]=\"entry\" [ngControl]=\"entry.fieldName\"&gt;&lt;\/control-wrapper&gt;\n        &lt;\/div&gt;\n\n    &lt;\/div&gt;\n\n    &lt;ng-content&gt;&lt;\/ng-content&gt;\n\n&lt;\/form&gt;\n<\/code><\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>And DynamicComponentLoader<\/p>\n","protected":false},"author":9,"featured_media":2997,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2481","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-unkategorisiert"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Dynamic Forms With Angular 2 - ANGULARarchitects<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Dynamic Forms With Angular 2 - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"And DynamicComponentLoader\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2019-04-10T10:11:37+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1280\" \/>\n\t<meta property=\"og:image:height\" content=\"853\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Manfred Steyer, GDE\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daniel\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer, GDE\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-forms-with-angular-2\/\"},\"author\":{\"name\":\"Manfred Steyer, GDE\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\"},\"headline\":\"Dynamic Forms With Angular 2\",\"datePublished\":\"2019-04-10T10:11:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-forms-with-angular-2\/\"},\"wordCount\":789,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"articleSection\":[\"Unkategorisiert\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-forms-with-angular-2\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/\",\"name\":\"Dynamic Forms With Angular 2 - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"datePublished\":\"2019-04-10T10:11:37+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"width\":1280,\"height\":853},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Dynamic Forms With Angular 2\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\",\"name\":\"Manfred Steyer, GDE\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer, GDE\"},\"sameAs\":[\"https:\/\/x.com\/daniel\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Dynamic Forms With Angular 2 - ANGULARarchitects","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/","og_locale":"en_US","og_type":"article","og_title":"Dynamic Forms With Angular 2 - ANGULARarchitects","og_description":"And DynamicComponentLoader","og_url":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/","og_site_name":"ANGULARarchitects","article_published_time":"2019-04-10T10:11:37+00:00","og_image":[{"width":1280,"height":853,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","type":"image\/jpeg"}],"author":"Manfred Steyer, GDE","twitter_card":"summary_large_image","twitter_creator":"@daniel","twitter_misc":{"Written by":"Manfred Steyer, GDE","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-forms-with-angular-2\/"},"author":{"name":"Manfred Steyer, GDE","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951"},"headline":"Dynamic Forms With Angular 2","datePublished":"2019-04-10T10:11:37+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-forms-with-angular-2\/"},"wordCount":789,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","articleSection":["Unkategorisiert"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-forms-with-angular-2\/","url":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/","name":"Dynamic Forms With Angular 2 - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","datePublished":"2019-04-10T10:11:37+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","width":1280,"height":853},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/dynamic-forms-with-angular-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Dynamic Forms With Angular 2"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951","name":"Manfred Steyer, GDE","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","caption":"Manfred Steyer, GDE"},"sameAs":["https:\/\/x.com\/daniel"]}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/2481","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=2481"}],"version-history":[{"count":0,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/2481\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/2997"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=2481"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=2481"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=2481"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}