1

I'm using a component factory to load in different components via a Block input which states characteristics of the block - internal variables. Then, depending on the variables set, the factory will load in different components.

Here's my code for the factory

import { Directive, Input, AfterContentInit, ComponentFactoryResolver, ViewChild, ViewContainerRef, Component } from '@angular/core';

import { GreenBlock } from './Blocks/GreenBlock';
import { BlueBlock } from './Blocks/BlueBlock';
import { YellowBlock } from './Blocks/YellowBlock';
import { Block } from './Block';


@Component({
  selector: 'block-factory',
  template: '<div #container></div>',
})
export class BlockFactory implements AfterContentInit  {

  @Input() block: Block;

  @ViewChild('container', {read: ViewContainerRef}) container;

  constructor(public resolver: ComponentFactoryResolver) 
  { 

  }

  ngAfterContentInit() {

    var content;

    switch(this.block.Type) 
    {
      case "yellow":
        content = this.resolver.resolveComponentFactory(YellowBlock);
      break;

      case "blue":
        content = this.resolver.resolveComponentFactory(BlueBlock);
      break;

      case "green":
        content = this.resolver.resolveComponentFactory(GreenBlock);
      break;

      default:
        content = this.resolver.resolveComponentFactory(YellowBlock);
      break;
    }

    let componentRef = this.container.createComponent(content);
    componentRef.instance.block = this.block;
  }
}

Then, to call this factory via HTML, I use the following notation:

<block-factory (ngModel)="newBlock" [block]="newBlock" style="margin:10px 5px;" ></block-factory>

The newBlock corresponds to the Block (A class holding some information related to the block), thus depending on what a set the block on screen will look a lot different.

Now, this newBlock changes depending on what the person picks from a drop-down box. See the following function:

// Set the new block via what is clicked in the dropdown box
setNewBlock(block) 
{
  this.newBlock = block;
}

A fairly simple function. Now, as expected the newBlock won't update with it's new "look" because Angular can't figure out any of the bindings if they aren't static components. My question is - how can I make Angulars binding function?

Johnathan Brown
  • 713
  • 12
  • 35
  • Hmm, not sure I understand the question, but I use ngZone [link](https://angular.io/api/core/NgZone) explicitly sometimes to make sure my view get updated correctly. If I'm on the right track perhaps some explicit change detection strategy [link](https://blog.angularindepth.com/these-5-articles-will-make-you-an-angular-change-detection-expert-ed530d28930) *pretty non opinionated link – BSchnitzel Apr 10 '18 at 19:58
  • I'm not sure if ngZone will help, I think the issue is the model is trying to do two way binding to the factory, rather then to component the factory loads. I don't know Angular well enough to try and design around this problem. I'm wondering if something like the mediator design pattern might help - not sure!! I'll read that article you linked, thanks – Johnathan Brown Apr 10 '18 at 20:08
  • Angular typically excels using structural directives IMO maybe put all the blocks in a block array using a *ngFor and perhaps a *ngIf for certain scenarios (if blue, yellow, green etc.) – BSchnitzel Apr 10 '18 at 20:54
  • Doesn't seem like a great solution though. – Johnathan Brown Apr 11 '18 at 04:40
  • @Bdrizzle I'm going to try to use an ngSwitch to see if that solves the issue with two-way binding. – Johnathan Brown Apr 11 '18 at 15:43
  • good luck. When coding with Angular it's best to try to keep things simple as possible. This way if you have to backtrack and troubleshoot your truth table is not 100 lines long lol! – BSchnitzel Apr 11 '18 at 16:10

0 Answers0