Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular 5: interchange locations of dynamic components

I want to interchange the positions of the dynamically placed components inside the view.

i.e. I have created components dynamically with id = 1 and 2 as shown in figure.

enter image description here

now I need to interchange the positions of both the components but how?

One thing I know (only theoratically) is location can be change through move method inside the ViewContainerRef class via object as viewContainerRef.move(componentRef.hostView, index).

I tried it but positions didn't interchange.

@ViewChild(ContainerRefDirective) location: ContainerRefDirective;

let componentFactory = this.factoryResolver.resolveComponentFactory(EntryComponent);
let componentRef = this.location.viewContainerRef.createComponent(componentFactory);

let entryComponent: EntryComponent = componentRef.instance;
// lets say counter is variable that increments its value on new component creation.
entryComponent.Id = ++counter; 

// move method is being called right after a new component is created and placed. 
//this piece of code is in the same method (that is creating the dynamic components)
this.location.viewContainerRef.move(componentRef.hostView, 1);

I have read the ViewContainerRef documentation on angular.io and read almost same question regarding this issue but could not understand or resolve this issue.

like image 880
WasiF Avatar asked Apr 03 '18 07:04

WasiF


People also ask

Where to dynamically load components in angular?

Now Angular knows where to dynamically load components. The <ng-template> element is a good choice for dynamic components because it doesn't render any additional output. Take a closer look at the methods in ad-banner.component.ts. AdBannerComponent takes an array of AdItem objects as input, which ultimately comes from AdService.

What is a componentfactory in angular?

Generally, the Angular compiler generates a ComponentFactory for any component referenced in a template. However, there are no selector references in the templates for dynamically loaded components since they load at runtime.

How do I use createcomponent() method in angular?

The createComponent () method returns a reference to the loaded component. Use that reference to interact with the component by assigning to its properties or calling its methods. Generally, the Angular compiler generates a ComponentFactory for any component referenced in a template.

How does angular know about a component at runtime?

This means that Angular knows about the component during build-time, but it only creates the component at runtime. One way (although deprecated) was to use the ComponentFactoryResolver.


1 Answers

I haven't tried this, but reading the docs sounds like move is not the correct method. Sounds like move is for "adding" an existing component to the view.

From the docs for detach:

Use along with insert to move a View within the current container.

Based on that line, I'd try ...

let ref = this.location.viewContainerRef;
ref.detach(ref.indexOf(componentRef.hostView));
ref.insert(componentRef.hostView, 0);

Edit I created a working example using Angular's live example for Dynamic Component Loader.

Here's the code relevant to the question:

// ShaneCoder - don't clear so we get multiple ads to demonstrate move.
// viewContainerRef.clear();

// ShaneCoder - only create 4 ads
if (viewContainerRef.length<4) {

    let componentRef = viewContainerRef.createComponent(componentFactory);
    (<AdComponent>componentRef.instance).data = adItem.data;

    // ShaneCoder ad is inserted at the bottom (no index parameter).  Move it up if there are multiple ads.
    if (viewContainerRef.length>=1) {
        // we're not the first ad
        // move new ad to top using detach and insert (the next two lines answer the original question) 
        viewContainerRef.detach(viewContainerRef.indexOf(componentRef.hostView));
        viewContainerRef.insert(componentRef.hostView, 0);
        // comment out the previous two lines to see that ads are inserted at the bottom.
    }
}

Edit 2

After posting the last edit realized I hadn't tried move. Switched the detach and insert out for a move and it works. Example here. Relevant code:

viewContainerRef.move(componentRef.hostView, 0);
// comment out the previous two lines to see that ads are inserted at the bottom.

Now I'm wondering if the problem you were fighting with move was its zero-index. To make a component the first in a container view you need to pass a zero for the index. To make it second pass a one and so on. So your code would change like such:

this.location.viewContainerRef.move(componentRef.hostView, 0);
like image 91
ShaneCoder Avatar answered Oct 14 '22 05:10

ShaneCoder