web-dev-qa-db-fra.com

Angular 6 - Est-il possible d'utiliser deux composants d'élément angular sur la même page)?

J'essaie d'héberger des éléments indépendants angular que je peux déposer dans une page Web non angulaire. Cela fonctionne très bien lorsque je n'en ai qu'une .. mais quand j'en charge deux ou plus sur la même page Je reçois cette erreur:

Erreur non interceptée: zone déjà chargée.

J'utilise un script de construction pour concaténer mes fichiers dist en un seul fichier js .. puis le déposer dans mon projet

const fs = require('fs-extra')
const concat = require('concat')


const files = [
    './dist/elementsApp/runtime.js',
    './dist/elementsApp/polyfills.js',
    './dist/elementsApp/scripts.js',
    './dist/elementsApp/main.js',
]


fs.ensureDir('elements')
.then(() => {
  console.log('success!')
  concat(files, 'elements/include-me-somewhere-else.js')
})
.catch(err => {
  console.error(err)
})

Je ne peux avoir qu'un de ces fichiers js sur une seule page. Je comprends angular 7 facilitera tout ce processus, mais je me demande comment je peux y arriver maintenant.

J'ai également essayé d'encapsuler mon fichier js exporté dans une fonction auto-exécutable pour essayer de limiter la portée .. Ne résout malheureusement rien.

Des idées?

Les gens semblent confus sur ce que angular sont. Pour des éclaircissements, vous pouvez regarder cette vidéo https://www.youtube.com/watch?v=4u9_kdkvTsc . La dernière quelques minutes en particulier montrent un élément angular exporté et inclus sur une page non angular. J'essaie d'inclure plusieurs éléments sur la même page).

28
hamobi

Je pense que vous ne devriez pas utiliser 2 angular sur un seul site.

Les solutions peuvent être:

  • Construisez l'ensemble du site en angulaire. D'autres parties du code peuvent être ajoutées à l'application.
  • Utilisez des sous-modules et fusionnez les deux applications avec un routeur parent.
  • Utilisez iframe pour chaque composant Angular. Alors ngzone ne se heurtera pas.
6
androbin

Voici donc mes réflexions basées sur notre discussion précédente. Parce que chaque bundle que vous créez avec un élément se charge dans zone.js vous obtenez des messages d'erreur:

Uncaught Error: Zone already loaded.

Ce que vous pouvez et devez considérer, ce n'est PAS de concaténer le './dist/elementsApp/polyfills.js' dans votre bundle (pour chaque élément que vous bundlez vous produisez). Utilisez plutôt le polyfill.js fichier en tant qu'importation distincte dans votre code HTML et importez-le avant tous les ensembles d'éléments que vous importez.

4
MichaelSolati

Google Polymer peut être ce que vous recherchez au lieu d'angulaire:

https://www.polymer-project.org/

La bibliothèque Polymer fournit un ensemble de fonctionnalités pour créer des éléments personnalisés. Ces fonctionnalités sont conçues pour faciliter et accélérer la création d’éléments personnalisés qui fonctionnent comme des éléments DOM standard.

2
Edward Newsome

Ceci est une solution qui fonctionne parfaitement sur angular 5+. For angular 6 je ne l'ai pas fait. Je l'ai fait pour un énorme projet CMS et j'ai composants insérés dans plusieurs pages et même 2 mêmes modules angular dans une seule page. Vous pouvez utiliser un projet angular.

dans votre site, écrivez les balises des composants.

Vous devez créer un autre module (par exemple mainHelper) pour exporter chaque balise angular angulaire).

import {NgModule, ApplicationRef, ComponentFactoryResolver} from '@angular/core';
import {FirstModule} from 'YOUR MODULE PATH';
import {FirstComponent} from 'YOU COMPONENT PATH';
import {SecondModule} from 'YOUR MODULE PATH';
import {SecondComponent} from 'YOU COMPONENT PATH';


@NgModule({
  imports: [
    FirstModule,
    SecondModule
  ],
})

export class MainHelper {
  constructor(private resolver: ComponentFactoryResolver) {
  }
  components = [
FirstComponent,
SecondComponent
  ];


  ngDoBootstrap(ref: ApplicationRef) {
    this.components.forEach((component) => {
      const factory = this.resolver.resolveComponentFactory(component);
      const elements = document.getElementsByTagName(factory.selector); //get angular tags on your main website
      if (elements.length > 0) {
        if (elements.length > 1) {
          const selector = factory.selector;
          for (let i = 0; i < elements.length; i++) {
            elements[i].id = selector + '-' + i;
            (<any>factory).factory.selector = '#' + elements[i].id;
            ref.bootstrap((<any>factory).factory);
            // elements[i].id = '';
          }
          (<any>factory).factory.selector = selector;
        } else {
          ref.bootstrap(component);
        }
      }
    });
  }
}

dans votre main.ts, vous pouvez importer le module MainHelper et bootstrap le MainHelper.

et votre FirstModule ressemblerait à ceci:

import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {BrowserModule} from '@angular/platform-browser'; 
import {FirstComponent} from './first.component';
import {AnotherComponent} from './another/another.component';
@NgModule({
  imports: [
    CommonModule,
    BrowserModule,
  ],
  providers: [
    SampleService // you need provide your services for all the modules
  ],
  declarations: [
    FirstComponent,
    AnotherComponent,
  ],
  bootstrap: [FirstComponent] // important
})
export class ECommerceModule {
}

J'espère que ceci vous aide.

1
m.akbari