通用/动态组件在多个模块之间共享

时间:2019-12-06 10:01:38

标签: javascript angular typescript

我正在尝试获取selector: data-collection。既可以同时通过ModuleA和ModuleB访问(可能会有更多的模块),也需要基于Module的路由(例如ModuleA和ModuleB)。但是,使用下面提供的代码,我遇到了以下错误。

Error: Type DataCollectionComponent is part of the declarations of 2 modules: ModuleAModule and ModuleBModule! Please consider moving DataCollectionComponent to a higher module that imports ModuleAModule and ModuleBModule. You can also create a new NgModule that exports and includes DataCollectionComponent then import that NgModule in ModuleAModule and ModuleBModule.

ModuleA.module.ts

@NgModule({
  declarations: [
    ModuleAComponent,
    ModuleACrudComponent,
    DataCollectionComponent,
    CrudModeComponent
  ],
  imports: [
    // CommonModule,
    CdkTableModule,
    MaterialModule,
    ReactiveFormsModule,
    ModuleARoutingModule,
    SharedModule
  ],
  providers: [APIService, GenericResolver, CrudAPIService, CrudModeComponent]
})
export class ModuleA{}

ModuleA-routing.module.ts

const moduleARoutes: Routes = [
  {
    path: '',
    component: ModuleAComponent,
  },
  {
    path: 'create',
    component: ModuleACrudComponent,
  },
  {
    path: 'edit/:id',
    component: ModuleACrudComponent,
    resolve: {
      genericRecord: GenericResolver
    }
  },
  {
    path: 'delete/:id',
    component: ModuleACrudComponent,
  }
];

@NgModule({
  imports: [RouterModule.forChild(moduleARoutes)],
  exports: [RouterModule]
})
export class ModuleARoutingModule {}

ModuleA.component.html

<data-collection
  [path]="url"
  [(columns)]="columnDefinitions"
  [genericForm]="form"
  [genericActionList]="actionList"
>
</data-collection>

ModuleB.module.ts

@NgModule({
  declarations: [
    ModuleBComponent,
    ModuleBCrudComponent,
    DataCollectionComponent
  ],
  imports: [
    // CommonModule,
    CdkTableModule,
    MaterialModule,
    ReactiveFormsModule,
    ModuleBRoutingModule,
    SharedModule
  ],
  providers: [APIService]
})
export class ModuleBModule {}

ModuleB-routing.module.ts


const moduleBRoutes: Routes = [
  {
    path: '',
    component: ModuleBComponent,
  },
  {
    path: 'create',
    component: ModuleBCrudComponent,
  },
  {
    path: 'edit/:id',
    component: ModuleBCrudComponent,
  },
  {
    path: 'delete/:id',
    component: ModuleBCrudComponent,
  }
];

@NgModule({
  imports: [RouterModule.forChild(moduleBRoutes)],
  exports: [RouterModule]
})
export class ModuleBRoutingModule {}

ModuleB.component.html

<data-collection
  [path]="url"
  [(columns)]="columnDefinitions"
  [genericForm]="form"
  [genericActionList]="actionList"
>
</data-collection>

data-table.component.html selector: data-collection

<!-- <ng-container *ngIf="!isInputDecValueEmpty()"> -->
<div class="mat-elevation-z12">
  <div class="parent-div">
    <div class="child-first-div">
      <mat-form-field class="container-12" appearance="outline">
        <input #globalSearch matInput name="search" />
        <mat-label>Type Here to Search All</mat-label>
        <button
          mat-button
          matSuffix
          mat-icon-button
          aria-label="Clear"
          (click)="searchClear()"
          matTooltip="Reset Your Search Result"
        >
          <mat-icon svgIcon="close"></mat-icon>
        </button>
      </mat-form-field>
      <mat-checkbox #checkBox class="btnShowDeleted" (change)="onChange()">
        Show Deleted Records
      </mat-checkbox>
    </div>
    <div class="child-second-div">
      <button
        *ngIf="genericActionList.canGoCreate"
        mat-raised-button
        color="primary"
        matTooltip="Create New Record"
        (click)="goToAdd()"
      >
        <mat-icon svgIcon="add"></mat-icon>
      </button>
      <button
        *ngIf="genericActionList.canGoCopy"
        mat-raised-button
        color="primary"
        matTooltip="Copy Record"
        (click)="goToCopy()"
      >
        Copy
      </button>
      <button
        *ngIf="genericActionList.canExport"
        mat-raised-button
        color="primary"
        matTooltip="Export to Excel"
        (click)="exportAsXLSX()"
      >
        <mat-icon svgIcon="assignment_returned"></mat-icon>
      </button>
    </div>
  </div>
  <hr />
  <br />

  <!-- <div style="padding: 32px"> -->
  <!-- <div class="example-container mat-elevation-z8"> -->
  <div>
    <div style="overflow: auto;">
      <div class="parent-spinner">
        <div class="spinner-container" *ngIf="loading$ | async">
          <mat-card>
            <mat-spinner color="primary" mode="indeterminate"></mat-spinner>
          </mat-card>
        </div>
        <form [formGroup]="genericForm">
          <table
            #table
            mat-table
            matSortDirection="asc"
            matSortDisableClear
            [dataSource]="dataSource"
            matSort
          >
            <ng-container *ngFor="let col of columns" [cdkColumnDef]="col.def">
              <!-- <mat-header-cell *cdkHeaderCellDef mat-sort-header> -->

              <!-- <ng-container *ngIf="col[0]">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>
              {{ col.header }}
            </th>
        </ng-container> -->

              <th mat-header-cell *matHeaderCellDef>
                <label
                  ><b mat-sort-header class="header-text">{{
                    col.header
                  }}</b></label
                >
                <div class="header-search-div">
                  <ng-container [ngSwitch]="col.dataType">
                    <ng-container *ngSwitchCase="1">
                      <mat-form-field
                        floatLabel="never"
                        class="mat-form-field-test"
                      >
                        <mat-label class="search-label"
                          >Search {{ col.header }}</mat-label
                        >
                        <input matInput formControlName="{{ col.def }}" />
                      </mat-form-field>
                    </ng-container>

                    <ng-container *ngSwitchCase="2">
                      <mat-form-field
                        floatLabel="never"
                        class="mat-form-field-test"
                      >
                        <mat-label class="search-label"
                          >Search {{ col.header }}</mat-label
                        >
                        <input
                          matInput
                          [matDatepicker]="picker"
                          formControlName="{{ col.def }}"
                        />
                        <mat-datepicker-toggle
                          matSuffix
                          [for]="picker"
                        ></mat-datepicker-toggle>
                        <mat-datepicker #picker></mat-datepicker>
                      </mat-form-field>
                    </ng-container>

                    <ng-container *ngSwitchCase="3">
                      <mat-form-field
                        floatLabel="never"
                        class="mat-form-field-test"
                      >
                        <mat-label class="search-label"
                          >Select Status</mat-label
                        >
                        <mat-select
                          disableRipple
                          formControlName="{{ col.def }}"
                        >
                          <!-- <mat-option value="">None</mat-option> -->
                          <ng-container
                            *ngFor="let ddList of col.option | keyvalue"
                          >
                            <mat-option value="{{ ddList.key }}">
                              {{ ddList.value }}</mat-option
                            >
                            <!-- <mat-option value="3">Amended</mat-option> -->
                          </ng-container>
                        </mat-select>
                      </mat-form-field>
                    </ng-container>

                    <ng-container *ngSwitchCase="4">
                      <mat-form-field
                        floatLabel="never"
                        class="mat-form-field-test"
                      >
                        <mat-label class="search-label"
                          >Select {{ col.header }}</mat-label
                        >
                        <mat-select
                          disableRipple
                          formControlName="{{ col.def }}"
                        >
                          <mat-option>-- Select {{ col.header }} --</mat-option>
                          <ng-container
                            *ngFor="let dropdown of genericDropDown$ | async"
                          >
                            <mat-option [value]="dropdown">
                              {{ dropdown }}
                            </mat-option>
                          </ng-container>
                        </mat-select>
                      </mat-form-field>
                    </ng-container>

                    <ng-container *ngSwitchCase="0">
                      <div style="padding: 10px 0 15px;">
                        <button
                          mat-icon-button
                          matTooltip="Search Record"
                          (click)="mapFilterValues()"
                        >
                          <mat-icon color="primary" svgIcon="search"></mat-icon>
                        </button>
                        <button
                          mat-icon-button
                          matTooltip="Reset Search"
                          (click)="clearIndivSearch()"
                        >
                          <mat-icon color="warn" svgIcon="refresh"></mat-icon>
                        </button>
                      </div>
                    </ng-container>
                  </ng-container>
                </div>
              </th>

              <ng-container *ngIf="col.selectable === true">
                <td mat-cell *matCellDef="let row">
                  <a
                    (click)="goToEdit(row[col.def])"
                    routerLink="edit/{{ row[col.def] }}"
                    >{{ row[col.def] }}
                  </a>
                </td>
              </ng-container>

              <ng-container *ngIf="col.dataType === 2">
                <td mat-cell *matCellDef="let row">
                  {{ row[col.def] | date: 'yyyy-MM-dd hh:mm:ss a' }}
                </td>
              </ng-container>

              <ng-container
                *ngIf="col.def !== enumRecordType && col.def !== 'Action'"
              >
                <td mat-cell *matCellDef="let row">{{ row[col.def] }}</td>
              </ng-container>

              <ng-container *ngFor="let rec of enumRecordType">
                <ng-container *ngIf="col.def === rec">
                  <td mat-cell *matCellDef="let row">
                    {{
                      col.def == 1
                        ? 'New'
                        : row[col.def] === 3
                        ? 'Amended'
                        : row[col.def] == 5
                        ? 'Deleted'
                        : ''
                    }}
                  </td>
                </ng-container>
              </ng-container>
              <!-- <td mat-cell *matCellDef="let row">
                  {{ row[col.def] | date: 'yyyy-MM-dd hh:mm:ss a' }}
                </td> -->
              <ng-container *ngIf="col.def === 'Action'">
                <td mat-cell *matCellDef="let row">
                  <button
                    mat-icon-button
                    matTooltip="Edit Record"
                    (click)="goToEdit(row)"
                  >
                    <mat-icon color="primary" svgIcon="launch"></mat-icon>
                  </button>
                  <button
                    mat-icon-button
                    matTooltip="Delete Record"
                    (click)="goToDelete(row)"
                  >
                    <mat-icon color="warn" svgIcon="delete_outline"></mat-icon>
                  </button>
                </td>
              </ng-container>
              <!-- <ng-container *ngIf="col.def === 'CHOP_NO'">
          <mat-header-cell *matHeaderCellDef>
            <router-outlet></router-outlet>
          </mat-header-cell>
        </ng-container> -->
            </ng-container>
            <tr mat-header-row *matHeaderRowDef="displayedColumns()"></tr>
            <!-- <mat-header-row *cdkHeaderRowDef>
        <router-outlet></router-outlet
      ></mat-header-row> -->
            <!-- <mat-header-row *matHeaderRowDef></mat-header-row> -->
            <tr mat-row *matRowDef="let row; columns: displayedColumns()"></tr>
          </table>
        </form>
      </div>
    </div>
    <ng-container *ngIf="zeroRecord$ | async">
      <mat-card>
        <div class="no-record">
          No Records Available. Please consider to add new data.
        </div>
      </mat-card>
    </ng-container>

    <ng-container *ngIf="noResults$ | async">
      <mat-card>
        <div class="no-record">
          No Results Found
        </div>
      </mat-card>
    </ng-container>
    <div class="container">
      <div class="page-select">
        <div class="label">Go to page:</div>
        <mat-form-field style="width: 60px;">
          <mat-select #goToPage (selectionChange)="jumpToPage()">
            <ng-container *ngFor="let numPages of pageSubject | async">
              <mat-option [value]="numPages">
                {{ numPages }}
              </mat-option>
            </ng-container>
          </mat-select>
          <input #goToPage [OnlyNumber]="true" matInput />
        </mat-form-field>

        <mat-paginator
          #paginator
          [showFirstLastButtons]="true"
          [pageSizeOptions]="[5, 10, 20, 100]"
        >
        </mat-paginator>
      </div>
    </div>
  </div>
</div>
<!-- </ng-container> -->

shared.module.ts

import { RecordNotFoundComponent } from './components/record-not-found/pages/record-not-found.component';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { OnlyNumber } from './directives/onlyNumber.directive';
import { HasPermissionDirective } from './directives/accessRights.directive';

@NgModule({
  declarations: [OnlyNumber, HasPermissionDirective, RecordNotFoundComponent],
  exports: [CommonModule, OnlyNumber, HasPermissionDirective, RecordNotFoundComponent]
})
export class SharedModule {}

1 个答案:

答案 0 :(得分:0)

如果要在应用程序模块之间使用组件。您必须将该组件放入共享模块中,然后从该共享模块中将其导出。您的情况是SharedModule。并且不要将该组件放到多个模块中。这就是为什么出现以下错误的原因:

  Error: Type DataCollectionComponent is part of the declarations of 2 modules: ModuleAModule and ModuleBModule! Please consider moving DataCollectionComponent to a higher module that imports ModuleAModule and ModuleBModule. You can also create a new NgModule that exports and includes DataCollectionComponent then import that NgModule in ModuleAModule and ModuleBModule.

要解决此问题,请将DataCollectionComponent添加到SharedModule并像下面这样导出该组件。

@NgModule({
  declarations: [OnlyNumber, HasPermissionDirective, RecordNotFoundComponent, DataCollectionComponent],
  exports: [CommonModule, OnlyNumber, HasPermissionDirective, RecordNotFoundComponent, DataCollectionComponent]
})

现在将其从其他模块中删除。

有关更多详细信息,请参阅他们的DOC here