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.
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.
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.
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.
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.
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.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With