Angular, moving components via class reference without creating / destroying them

Viewed 50

So I'd like to move an angular component and I am well aware I can do it via construction and destruction such as this example: https://stackblitz.com/edit/angular-t3rxb3?file=src%2Fapp%2Fapp.component.html

However I have a scenario that my components are already part of the dom and would like to simple move them around in the dom as is (not create but just move location in dom).

I have a reference to source and destination class locations:

const dom: HTMLElement = this.el.nativeElement;
const elements1 = dom.querySelectorAll('.sourceClass');
const elements2 = dom.querySelectorAll('.destinationClass');

looked online but examples don't seem to have move only and want to avoid jQuery by all means.

and if I was using jQuery I'd use

jQuery('.destination').appendTo('.source');

which works well... Thanks

Sean

2 Answers

I'm really not sure what exactly you want, but I'd say the Renderer2 would fit your need.

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1> 
  <child1 #child1></child1>
  <div #enmptyBox class="empty-box">
  </div>
  <br>
  <button (click)='moveChild1()'>move comp1 to empty box</button>
  `,
  styles: [`h1 { font-family: Lato; } .empty-box{border: 1px dotted; height: 100px; width: 500px}`]
})
export class HelloComponent {
  @Input() name: string;
  @ViewChild("child1", { read: ElementRef }) child1;
  @ViewChild("enmptyBox", { read: ElementRef }) enmptyBox;

  constructor(private elRef:ElementRef, private renderer: Renderer2) {}

  moveChild1() {
    // first approach 
    this.renderer.appendChild(this.enmptyBox.nativeElement,this.child1.nativeElement);
    // second approach
    this.renderer.appendChild(this.elRef.nativeElement.querySelector('.empty-box'),this.child1.nativeElement);
  }
}

here's a complete stackblitz demo

Thanks for the support. So using class is not possible as far as as my tests since you will not get the proper nativeElement. ViewChild elementRef is a problem as my components are created dynamically. So I opted for the following. In the component I want to get a reference to, instead of parsing via DOM I maintain its own elementRef via:

    @ViewChild('tableList', {read: ElementRef}) tableListsComp;

    constructor() {
    }

    ngAfterViewInit() {
        if (this.field.inputType === 'tablelist') {
            this.elementRefs = this.tableListsComp;
        }
    }

and I grab it at a later via this.elementRefs using a service which the component is registered with.

once i have the instance I can do:

const compRef1 = this.getFormComponentViaServiceRef('Page');
this.render.appendChild(this.tab1.nativeElement, compRef1.componentRef.instance.elementRefs.nativeElement);

Thanks for the help.

Related