4
votes

I need help as I am a bit lost right now. So, I have a component that dynamically injets a child component into its template using componentFactoryResolver , here is my HTML

<div class="dialog">
    <div #container></div>
    <button (click)="move('back')">Back</button>
    <button (click)="move('forwards')">Forwards</button>
</div>

also in my component I have an observable that captures the click of the buttons like so, here is my (edited / reduced) code

// parent-component.ts

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

public navigationClick$: Observable<string> = new Subject<string>();

// click event on buttons
public move(direction): void {
    this.navigationClick$.next(direction);
}

// code to inject child dynamic component, please ignore the args / variables

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.data.component);
this.componentRef = this.dialogContainer.createComponent(componentFactory);
this.embeddedcomponent = this.componentRef.instance as IWizardDialog;
this.embeddedcomponent.data = this.data.data;

Now I would like to pass the latest observable value from navigationClick$ to the child component I amend the code in my parent component thus...

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.data.component);
this.componentRef = this.dialogContainer.createComponent(componentFactory);

// NEW CODE
// here I subscribe to the observable and try to pass the value to the child component
this.navigationClick$.subscribe((data: string) => {
  this.componentRef.instance.direction = data;
});

this.embeddedcomponent = this.componentRef.instance as IWizardDialog;
this.embeddedcomponent.data = this.data.data;

The subscribe is working in the parent as I would expect however I am unsure how I would capture / pass the subscribe data to the child component, for example can I just declare this as a Input()

// child-component.ts

@Input() public direction: string;

However this will just be undefined and isn't what I need. How do I pass the direction data from the subscribe to the child component or what code / feature do I need to receive the event / direction string? Any advice is appreciated.

If my wording is bad or confusing please say and I will rework the question.

1
How do you whant the application to behave if the user hits the browser backbutton? Do you want it to do the same as <button (click)="move('back')">Back</button>. Or do you want it to go to the last page the user visited. If you want it to step one 'dialog' back you should use angular routing. Move back and forward could be a [routerLink] to the same page with a different url parameter. - Jens Alenius
The behaviour doesn't matter, I am navigating data not the window, I just want to pass the string to the child, everything is taken care of. - Mark Sandman
Ok answer comming up - Jens Alenius

1 Answers

3
votes

I would use a service. Not ViewChild. With a service the components would not need to know of each other

 @Injectable()
  export class YourService {
  move$: Observable<any>;
  private moveSubject: Subject<any> = new Subject();

  constructor() {
    this.move$ = this.moveSubject.asObservable();
  }

  public move(direction) {
     this.moveSubject.next(direction);
  }


}

Usage in parent

contructor(public yourService:YourService){
}

html in parent

<button (click)="yourService.move('back')">Back</button>

Usage in child

YourChild implements OnInit, OnDestroy {
    private subscriptions: Subscription = new Subscription();
    constructor(private yourService:YourService) {

    }
    ngOnInit(): void {
        this.subscriptions.add(this.yourService.move$.subscribe(direction => {
            //Do something
        }));        
    }
    ngOnDestroy(): void {
    this.subscriptions.unsubscribe();
}

}