Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootstrap the same angular2 module multiple times in a page

Tags:

angular

I have a web forms application which loads User controls dynamically onto a page based on configurations (Just like a CMS with re-usable widgets). I would like to implement one of the user control/widget using an Angular2 component.

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Ng2Widget.ascx.cs" Inherits="Namespace.Ng2Widget" %>
<div>
     <app-root inputValue="<%= settingsValue %>"></app-root>
</div>

"settingsValue " will be a server side variable with some value which the server wants to pass on to the component.

So if the admin configures the page with multiple widgets of this newly implemented widget, the rendered page will have multiple Angular2 components of same type.

The rendered page will basically have

<div>
         <app-root inputValue="settingsValue1"></app-root>
</div>
<!-- Some other widgets -->
<div>
         <app-root inputValue="settingsValue2"></app-root>
</div>

Inorder to pass values into the root component, I used the method mentioned in this post. Angular 2 input parameters on root directive

At the bottom of the page I have placed the js files which bootstraps the module to .

<script type="text/javascript" src="ng2/dist/inline.bundle.js"></script>
<script type="text/javascript" src="ng2/dist/styles.bundle.js"></script>
<script type="text/javascript" src="ng2/dist/main.bundle.js"></script>

Once the page is loaded, Angular bootstraps the module only to the first instance of tag and completely ignores the second.

All the examples I find on the net, is trying to bootstrap multiple modules of different module types, which seems to work fine.

In Angular1, the root app was scoped to a dom element, and any dom element with that decorated with the ng-controller attribute loaded the components in their respective places.

In the earlier version of Angular2, we were able to bootstrap a component. But with the introduction of NgModule, a module is being bootstrapped. But even then I dont think the same component can be bootstrapped to multiple instances.(ie. All the instances of tag, renders the component.)

I saw the discussion regarding the same at https://www.reddit.com/r/Angular2/comments/424nwn/using_angular_2_without_it_being_a_single_page_app/

I feel this is relevant wherever a legacy server side driven app is trying to make use of client side frameworks like Angular2. I was able to make use of React components pretty easily since they are rendered and attached to a dom element at run time with a simple render method call.

Is there any way/workaround in which I can bootstrap multiple instances of the same module in a page? ie. Load the components in all the occurrences of the tags.

like image 483
rmchndrng Avatar asked Nov 24 '16 09:11

rmchndrng


2 Answers

I have exactly the same problem, after digging the web, I finally found the solution in this plnkr:

https://plnkr.co/edit/I6kxKa78Np73sIWbbYHz?p=preview

The magic part lies in the ngDoBootstrap function:

ngDoBootstrap(appRef : ApplicationRef) {
    this.components.forEach((componentDef : {type: Type<any>, selector: string}) => {
      const factory = this.resolver.resolveComponentFactory(componentDef.type);
      factory.selector = componentDef.selector;
      appRef.bootstrap(factory);
    });
}

Idea is to inject your list of component instances in the wrapper module and to bootstrap every component retreived by the ComponentFactoryResolver.

Hope this help.

like image 159
mth.vidal Avatar answered Nov 15 '22 09:11

mth.vidal


This works for angular5:

export class DetailOfferAppModule {

    constructor(private resolver: ComponentFactoryResolver) {

    }

    ngDoBootstrap(appRef: ApplicationRef) {

        ...

        //find matching elements on the page and bootstrap each one
        var elements = $('my-widget').toArray();
        if (elements && elements.length > 0) {

            elements.forEach(sectionElement => {
                appRef.bootstrap(MyComponent, sectionElement);
            });
        }
    }
}

HTML

<my-widget id="widgetA"></my-widget>
<my-widget id="widgetB"></my-widget>
like image 29
vidalsasoon Avatar answered Nov 15 '22 08:11

vidalsasoon