title: Angular 5 - Remove DOM Elements, View Won't Refresh
body: <p>I have a tag type search with two columns in the view, right column for categories and left for subcategories. The user clicks on a category tag, I use buttons, and the right column displays a selection of subcategory tags for a specific db query.</p>
  <p>This code works fine for the first call for subcategory tags from a category tag but after the user clicks on another category it adds the appropriate tags to the view but the former subcategory tags are still there.  The previous tags need to be removed.</p>
  <p>However when I remove the old subcategory tags from the DOM with removeTags(event) below the tag data populates the instance correctly but the DOM doesn't have the new subcategory tags after the factory runs for those.  Nothing is there. No tag nodes are in the
  HTMLCollection in the ViewContainerRef.  This is the problem to fix.  Any ideas?</p>
  <p>Beginning of the remove function shows the first selection of subcategory tags in console.log:</p>
  <pre class="lang-html prettyprint-override"><code>    &lt;div class=&quot;tag-column&quot; fxflex=&quot;50%&quot; fxlayout=&quot;column&quot; ...&gt;
          &lt;template&gt;&lt;/template&gt;
          &lt;app-tag-button&gt;&lt;/app-tag-button&gt;
          &lt;app-tag-button&gt;&lt;/app-tag-button&gt;
          &lt;app-tag-button&gt;&lt;/app-tag-button&gt;
          &lt;app-tag-button&gt;&lt;/app-tag-button&gt;
      &lt;/div&gt;
  </code></pre>
  <p>And after removal the factory function creates new tag instances but they aren't in the DOM.  They should be:</p>
  <pre class="lang-html prettyprint-override"><code>    &lt;div class=&quot;tag-column&quot; fxflex=&quot;50%&quot; fxlayout=&quot;column&quot; ...&gt;
          &lt;template&gt;&lt;/template&gt;
      &lt;/div&gt;
  </code></pre>
  <p>The issue is in subCatTagFactory(data). (Complete function in the full code below this):</p>
  <pre class="lang-js prettyprint-override"><code>    const factory = this.resolver.resolveComponentFactory(CatTagButtonComponent);
  
      this.catComponentRef = this.categoryTagContainer.createComponent(factory);
  
      // Post tags to the view.
      this.catComponentRef.instance.categoryName = categoryName;
      this.catComponentRef.instance.categoryId = categoryId;
  </code></pre>
  <p>The instance is populated well.  No problem there.  I can see all the data in console.logs  They just won't turn into visible tags after the removal process.</p>
  <p>I added this change detection function to refresh the DOM after the removal step but it doesn't work.  This is my first time with change detection so probably not doing something right.  I tried various setups, this is the last attempt to get it right.</p>
  <pre class="lang-js prettyprint-override"><code>    private changeDetection(event) {
          this.changeDetect.markForCheck();
          // this.changeDetect.detach();
          // this.changeDetect.reattach();
          this.changeDetect.detectChanges();
          // Call for  subcat tags to load after a category button click.
          this.getSubCategoryTags(event);
        }
  </code></pre>
  <p>I'm importing the following classes to this module:
  ViewContainerRef,ComponentFactoryResolver, ComponentRef, Input, ChangeDetectorRef</p>
  <p>The code to remove the first selection of subcategory tags / buttons and create new ones.  The code above this in the full component creates category tags and works fine but I don't need to load new category tags.  The code for the category (not included below) and subcategory tags is almost identical.</p>
  <pre class="lang-js prettyprint-override"><code>    private removeTags(event) {
      
          //  The if() is for the first call for subcategory tags
          //  when there are not tags yet to remove.  Works fine.
          //  else {} is to remove previous tags.  This also works well.
  
          if (this.childNodes === undefined) {
            this.parentNode = document.getElementById('tagParent');
            // Call for tag to load after button click.
            this.getSubCategoryTags(event);
      
            this.parentNode = document.getElementById('tagParent');
            
            this.childNodes = this.parentNode.getElementsByTagName('app-tag-button');
  
            this.childLength = this.childNodes.length;
      
          } else {
  
            //  Cycle through childNodes var and remove, &lt;template&gt; child not in childNodes.
  
            while (this.childNodes[0]) {
      
              // Remove tags and prepare to receive new subcat tags below.
              // Remove buttons inside the tag elements
              this.childNodes[0].parentNode.removeChild(this.childNodes[0]);        
              
              // Remove element tags &lt;app-tab-button&gt;.
              this.childNodes[0].remove();
      
              // Resets to 0 for next call for subcat tags.
              this.childLength = this.childNodes.length;
            }
  
            // Call to refresh the view.
            this.changeDetection(event);
          }
        }
      
      
        //    |
        //    |
        //    |
        //    V
      
        private changeDetection(event) {
          this.changeDetect.markForCheck();
          // this.changeDetect.detach();
          // this.changeDetect.reattach();
          this.changeDetect.detectChanges();
  
          // Call for  subcat tags to load after category button click.
          this.getSubCategoryTags(event);
        }
      
      
        // ----- SUBCATEGORY TAGS ------
      
        // Prepare tag call for searching records in db.
      
        private getSubCategoryTags(categoryId) {
      
          // Params set in the parent and brought here with @Input().
          this.httpService.getSubCatTags(this.subCategoryTable, 'category_id', categoryId)
            .map(data =&gt; data.resource) // Get objects inside the JSON resource array.
            // switchMap strips off array index number to create JS objects.
            .switchMap(data =&gt; data)
            .subscribe(data =&gt; {
                this.subCatTagFactory(data);
              },
              (err: HttpErrorResponse) =&gt; {
                console.log(err.error);
                console.log(err.message);
                this.messagesService.openDialog('Error', 'Maybe database not available.');
              });
        }
      
        //    |
        //    |
        //    |
        //    V
      
        // Called from getCategoryTags() to create category tag button instances in factory.
      
        private subCatTagFactory(data) {
          const subCatTagName = data.skill_name;
          const subCatTagId = data.skill_id;
      
          // Create factory from ComponentRef&lt;SubCatTagButtonComponent&gt;
  
          const factory = this.resolver.resolveComponentFactory(SubCatTagButtonComponent);
      
          // Create new reference object for each tag as data received from db through observable.
  
          this.subCatComponentRef = this.subCatTagContainer.createComponent(factory);
      
          this.subCatComponentRef.instance.categoryName = subCatTagName;
          this.subCatComponentRef.instance.categoryId = subCatTagId;
      
          // Includes all new data on second call, works.
          console.log('subCatComponentRef: ', this.subCatComponentRef);
      
          console.log('parentNode after instantiation: ', this.parentNode);
          //  No tag children. Only &lt;template&gt;&lt;/template&gt;  
          //  This is the problem.  See near top of this post for console.log showing after first tags and after second tag instantiation.
          //  The data exists in the instances but not in the view template the second time.
          //  Data is not binding to the template the second time!
      
          // Subcat tag button click event calls sub category db query and retrieves list of records into Mat Table.
          // Not relevant for this SO issue.
          this.subCatComponentRef.instance.output.subscribe(event =&gt; this.httpService.getSubCatQuery(event, this.dbTable));
        }
      
      }
  </code></pre>