title: Replace a string with reactive form element
body: <p>I get string content from a 3rd party API; the content is created using a Wysiwyg so it can have any number of html tags within it.  I need to replace some strings with select lists.</p>
  <p>So, I might have a string like this:</p>
  <pre><code>&lt;p&gt;There are [howmany] dropdowns in this question&lt;/p&gt;
  </code></pre>
  <p>Within the angular app, I want the final result to be:</p>
  <pre class="lang-html prettyprint-override"><code>&lt;p&gt;There are 
    &lt;select&gt;
      &lt;option value=&quot;1&quot;&gt;One&lt;/option&gt;
      &lt;option value=&quot;2&quot;&gt;Two&lt;/option&gt;
    &lt;/select&gt; dropdowns in this question
  &lt;/p&gt;
  </code></pre>
  <p>I have all the replacement logic worked out, what I'm struggling with is maintaining the layout from the Wysiwyg <strong>and</strong> having a working form.</p>
  <h1>Attempt 1</h1>
  <p>My idea was to use a pipe:</p>
  <p><strong>component.ts</strong></p>
  <pre class="lang-js prettyprint-override"><code>multipleDropDownForm: FormGroup;
  ...
  ...
  ngOnInit(): void {
    this.generateForm();
    this.formString = new DropdownsPipe().transform(this.formStringParts, this.replacementVariables, this.multipleDropDownForm);
  }
  
  generateForm(): void {
    const group: any = {};
    this.replacementVariables.forEach(item =&gt; {
      group[item.asString] = new FormControl(item.asString, Validators.required);
    });
  
    this.multipleDropDownForm = new FormGroup(group);
  }
  </code></pre>
  <p><strong>component.html</strong></p>
  <pre class="lang-html prettyprint-override"><code>&lt;div class=&quot;question__lead-in&quot; [innerHTML]=&quot;formString&quot;&gt;
    &lt;/div&gt;
  </code></pre>
  <p><strong>dropdowns.pipe.ts</strong></p>
  <pre class="lang-js prettyprint-override"><code>export class DropdownsPipe implements PipeTransform {
    transform(value: string[], replacementVars: ReplacementVariable[], form: FormGroup): any {
      let compiledString = `&lt;div [formGroup]=${form}&gt;`;
      value.forEach(v =&gt; {
        if (replacementVars.find(r =&gt; r.withBrackets === v) === undefined) {
          compiledString += v;
        } else {
          const rv = replacementVars.find(rvf =&gt; rvf.withBrackets === v);
          let select = `&lt;select name=&quot;${rv.asString}&quot; formControlName=&quot;${rv.asString}&quot;&gt;`;
          rv.answerOptions.forEach(ao =&gt; {
            select += `&lt;option value=&quot;${ao.id}&quot;&gt;${ao.text}&lt;/option&gt;`;
          });
          select += '&lt;/select&gt;';
  
          compiledString += select;
        }
      });
      compiledString += '&lt;/div&gt;';
      return compiledString ;
    }
  }
  </code></pre>
  <p>From a presentation only point of view, this works great - I get the exact HTMl that is provided by the wysiwyg.  Functionally, it doesn't work.  Submitting the form simply shows the default controls as value:</p>
  <p><a href="https://i.stack.imgur.com/IRTVX.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/IRTVX.png" alt="enter image description here" /></a></p>
  <p>The html output for this method is:
  <a href="https://i.stack.imgur.com/VBf1s.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/VBf1s.png" alt="enter image description here" /></a></p>
  <p>I'm only guessing that doing it this way doesn't allow Angular to properly register the <code>select</code> elements as form controls.</p>
  <h1>Attempt 2</h1>
  <p>Use components</p>
  <p><strong>select-list.component.html</strong></p>
  <pre class="lang-html prettyprint-override"><code>&lt;ng-container [formGroup]=&quot;form&quot;&gt;
    &lt;select name=&quot;{{ replacement.asString }}&quot; formControlName=&quot;{{ replacement.asString }}&quot;&gt;
      &lt;option *ngFor=&quot;let option of replacement.answerOptions&quot; value=&quot;{{ option.id }}&quot;&gt;{{ option.text }}&lt;/option&gt;
    &lt;/select&gt;
  &lt;/ng-container&gt;
  </code></pre>
  <p><strong>component.html</strong></p>
  <pre class="lang-html prettyprint-override"><code>&lt;ng-container *ngFor=&quot;let s of formStringParts&quot;&gt;
      &lt;ng-container *ngIf=&quot;isReplacementVariable(s); else textLabelBlock&quot;&gt;
        &lt;app-select-list [form]=&quot;multipleDropDownForm&quot; [replacement]=&quot;getReplacementVariable(s)&quot;&gt;&lt;/app-select-list&gt;
      &lt;/ng-container&gt;
      &lt;ng-template #textLabelBlock&gt;&lt;span [innerHTML]=&quot;domSanitizer.bypassSecurityTrustHtml(s)&quot;&gt;&lt;/span&gt;&lt;/ng-template&gt;
    &lt;/ng-container&gt;
  </code></pre>
  <p>Functionally, this works great.  It fails on presentation though because I end up with something like this as the HTML:</p>
  <p><a href="https://i.stack.imgur.com/aRwnl.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/aRwnl.png" alt="enter image description here" /></a></p>
  <p>And this as the display (minor difference here, but could be more pronounced with more complicated HTML).  The image also shows that the correct values are available on submit.</p>
  <p><a href="https://i.stack.imgur.com/AeGUc.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/AeGUc.png" alt="enter image description here" /></a></p>
  <p>The HTML output for this method is:
  <a href="https://i.stack.imgur.com/ICOLO.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ICOLO.png" alt="enter image description here" /></a></p>
  <p>Is there a way to replace (n) strings with respective select lists that allows me to maintain the HTML from the API and work with submitting the form?</p>