Hi there.
I have a problem with services that I used into lazy loading components.
when I want to use in html of each sub components, Angular parser get me an error.
I want to import a service globally once, but sub components need to inject a service in it.
but when a service imported into app.module.ts, then sub components can’t seen in that scope.z
could anyone please help to resolve my problem?
App.module.ts
// angular core imports
import {BrowserModule} from '@angular/platform-browser';
import {NgModule, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
import {Component} from '@angular/core';
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {routes} from './app.router';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatCoreModule} from './mat-core/mat-core/mat-core.module';
// environment
import {environment} from '../environments/environment';
// global services imports
import {AuthGuardService} from './auth-guard.service';
// pipes import
import {FilterMemberPipe} from './pipes/filter-member.pipe';
// directives import
import {ClickStopPropagationDirective} from './directives/click-stop-propagation.directive';
import {FullCalendarDirective} from './directives/full-calendar.directive';
import {AccessUserDirective} from './directives/access-user.directive';
// plugins components import
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import 'hammerjs';
import {LayoutModule} from '@angular/cdk/layout';
import {AreaChartModule} from '@swimlane/ngx-charts';
import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {AmazingTimePickerModule} from 'amazing-time-picker';
import {PerfectScrollbarModule, PERFECT_SCROLLBAR_CONFIG, PerfectScrollbarConfigInterface} from 'ngx-perfect-scrollbar';
const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = {
suppressScrollX: true
};
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
// components import
import {LoginComponent} from './components/login/login.component';
import {MemberComponent} from './components/member/member.component';
import {ProjectComponent} from './components/project/project.component';
import {DashboardComponent} from './components/dashboard/dashboard.component';
import {WidgetsComponent} from './components/widgets/widgets.component';
import {BoardComponent} from './components/board/board.component';
import {MemberDetailComponent} from './components/member/member-detail/member-detail.component';
import {RolesComponent} from './components/roles/roles.component';
import {PermissionsComponent} from './components/permissions/permissions.component';
import {PermissionDetailComponent} from './components/permissions/permission-detail/permission-detail.component';
import {RoleDetailComponent} from './components/roles/role-detail/role-detail.component';
import {FeaturesComponent} from './components/project/features/features.component';
import {SubFeaturesComponent} from './components/project/sub-features/sub-features.component';
import {MissionsComponent} from './components/project/missions/missions.component';
import {VisionsComponent} from './components/project/visions/visions.component';
import {ReleasesComponent} from './components/project/releases/releases.component';
import {MeetingComponent} from './components/meeting/meeting.component';
import {IssueComponent} from './components/issue/issue.component';
import {WallpaperComponent} from './components/wallpaper/wallpaper.component';
import {AddProjectComponent} from './components/project/add-project/add-project.component';
import {ProjectDetailComponent} from './components/project/project-detail/project-detail.component';
import {ProjectOverviewComponent} from './components/project/project-detail/project-overview/project-overview.component';
import {ProjectCalendarComponent} from './components/project/project-detail/project-calendar/project-calendar.component';
import {ProjectFilesComponent} from './components/project/project-detail/project-files/project-files.component';
import {TaskComponent} from './components/task/task.component';
import {TaskDetailComponent} from './components/task/task-detail/task-detail.component';
import {VisionDetailComponent} from './components/project/visions/vision-detail/vision-detail.component';
import {MissionDetailComponent} from './components/project/missions/mission-detail/mission-detail.component';
import {ReleaseDetailComponent} from './components/project/releases/release-detail/release-detail.component';
import {FeatureDetailComponent} from './components/project/features/feature-detail/feature-detail.component';
import {SubFeatureDetailComponent} from './components/project/sub-features/sub-feature-detail/sub-feature-detail.component';
import {ProjectMembersComponent} from './components/project/project-members/project-members.component';
import {ProjectMembersDetailComponent} from './components/project/project-members/project-members-detail/project-members-detail.component';
import {ReportDetailComponent} from './components/report/report-detail/report-detail.component';
import {ApproveComponent} from './components/approve/approve.component';
import {SnackBarComponent} from './components/snack-bar/snack-bar.component';
import {TodoComponent} from './components/todo/todo.component';
import {AddTaskComponent} from './components/task/add-task/add-task.component';
import {BirthdayComponent} from './components/birthday/birthday.component';
import {MeetingDetailComponent} from './components/meeting/meeting-detail/meeting-detail.component';
// components modules
import {RouterModule} from '@angular/router';
import {ReportModule} from './components/report/report.module';
import {ProjectModule} from './components/project/project.module';
import {ViewDirectionService} from './services/view-direction.service';
@Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>',
})
export class AppComponent {
title = 'app';
}
@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent,
WidgetsComponent,
BoardComponent,
/*ProjectComponent,*/
MemberComponent,
MemberDetailComponent,
ClickStopPropagationDirective,
FeaturesComponent,
SubFeaturesComponent,
MissionsComponent,
VisionsComponent,
ReleasesComponent,
MeetingComponent,
IssueComponent,
WallpaperComponent,
AddProjectComponent,
/* ProjectDetailComponent,*/
ProjectOverviewComponent,
ProjectCalendarComponent,
ProjectFilesComponent,
TaskComponent,
FullCalendarDirective,
TaskDetailComponent,
FilterMemberPipe,
VisionDetailComponent,
MissionDetailComponent,
ReleaseDetailComponent,
FeatureDetailComponent,
SubFeatureDetailComponent,
ProjectMembersComponent,
ProjectMembersDetailComponent,
ReportDetailComponent,
ApproveComponent,
SnackBarComponent,
TodoComponent,
AddTaskComponent,
BirthdayComponent,
RolesComponent,
PermissionsComponent,
PermissionDetailComponent,
RoleDetailComponent,
AccessUserDirective,
MeetingDetailComponent
],
imports: [
MatCoreModule, // all material components in this module
FormsModule,
HttpClientModule,
ReactiveFormsModule,
BrowserModule,
BrowserAnimationsModule,
LayoutModule,
AmazingTimePickerModule,
AreaChartModule,
PerfectScrollbarModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
ReportModule,
ProjectModule,
RouterModule.forRoot(routes, {useHash: environment.production})
],
providers: [
AuthGuardService,
ViewDirectionService,
{
provide: PERFECT_SCROLLBAR_CONFIG,
useValue: DEFAULT_PERFECT_SCROLLBAR_CONFIG
}
],
bootstrap: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
entryComponents: [
MemberDetailComponent,
RoleDetailComponent,
PermissionDetailComponent,
WallpaperComponent,
AddProjectComponent,
AddTaskComponent,
VisionDetailComponent,
MissionDetailComponent,
ReleaseDetailComponent,
FeatureDetailComponent,
SubFeatureDetailComponent,
ProjectMembersDetailComponent,
ReportDetailComponent,
ApproveComponent,
SnackBarComponent,
MeetingDetailComponent
],
})
export class AppModule {
}
component’s html:
<div class="page-title-tab full-width" [dir]="rtlDirection ? 'rtl' : 'ltr'">
<h1 class="mat-h1 page-title font-full-em no-margin text-white"
[ngClass]="rtlDirection ? 'float-right' : 'float-left'">{{'GLOBAL.PROJECTS' | translate}}</h1>
<button mat-raised-button
(click)="showNewProjectDialog()"
class="btn-rounded btn-add blue-gradient text-white overflow-hide text-weight-normal"
[ngClass]="rtlDirection ? 'float-left' : 'float-right'">
<mat-icon>add</mat-icon>
<span class="button-title padding-mini-r-l">{{'PROJECT.CREATE_PROJECT' | translate}}</span>
</button>
<mat-card class="btn-rounded filter-card mat-elevation-z3 margin-r-l no-padding"
[dir]="rtlDirection ? 'rtl' : 'ltr'"
[ngClass]="[rtlDirection ? 'float-left' : 'float-right', showFilter ? 'active-filter' : '']">
<a (click)="toggleFilterMenu()"
matRipple
class="full-height display-block text-center"
[matTooltip]="showFilter ? ['FILTER.CLEAR_FILTER' | translate] : ['FILTER.FILTER_LIST' | translate]"
[matTooltipPosition]="'below'"
[ngClass]="[rtlDirection ? 'float-right' : 'float-left', showFilter ? 'text-red-400' : '']">
<mat-icon>
{{showFilter ? 'clear' : 'filter_list'}}
</mat-icon>
</a>
<div *ngIf="showFilter" [ngClass]="rtlDirection ? 'float-left' : 'float-right'">
<mat-form-field *ngIf="canShowFilter('PRIORITY')"
class="font-7-em filter-fields select-priority pos-rel margin-r-l"
[ngClass]="rtlDirection ? 'float-left' : 'float-right'">
<mat-select>
<mat-option class="font-8-rem">
{{"BOARD.PRIORITY" | translate}}
</mat-option>
<mat-option value="option1">
<mat-icon class="text-grey-500 font-full-em margin-t-half">flag</mat-icon>
<span class="font-8-em">{{"BOARD.PRIORITY_LOW" | translate}}</span>
</mat-option>
<mat-option value="option2">
<mat-icon class="text-blue-500 font-full-em margin-t-half">flag</mat-icon>
<span class="font-8-em">{{"BOARD.PRIORITY_NORMAL" | translate}}</span>
</mat-option>
<mat-option value="option3">
<mat-icon class="text-amber-500 font-full-em margin-t-half">flag</mat-icon>
<span class="font-8-em">{{"BOARD.PRIORITY_HIGH" | translate}}</span>
</mat-option>
<mat-option value="option3">
<mat-icon class="text-red-500 font-full-em margin-t-half">flag</mat-icon>
<span class="font-8-em">{{"BOARD.PRIORITY_URGENT" | translate}}</span>
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="canShowFilter('ASSIGNEE')"
class="font-7-em filter-fields pos-rel margin-r-l"
[ngClass]="rtlDirection ? 'float-left' : 'float-right'"
[floatLabel]="'never'">
<input matInput
placeholder="{{'PROJECT_FILTER.TYPE.ASSIGNEE' | translate}}"
[formControl]="myControl"
aria-label="Member"
[matAutocomplete]="memberIdSelect"
#memberName>
<mat-autocomplete #memberIdSelect="matAutocomplete">
<mat-option class="no-padding"
[style.opacity]="!member.isActive ? '.5' : '1'"
[disabled]="!member.isActive"
*ngFor="let member of filteredOptions | async" [value]="member">
<span class="text-teal-800 user-name-family font-8-em padding-mini-r-l">
{{member.name}} {{member.family}}
</span>
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field *ngIf="canShowFilter('CREATED_BY')"
class="font-7-em filter-fields pos-rel margin-r-l"
[ngClass]="rtlDirection ? 'float-left' : 'float-right'"
[floatLabel]="'never'">
<input matInput placeholder="{{'PROJECT_FILTER.TYPE.CREATED_BY' | translate}}"
aria-label="Member"
[matAutocomplete]="memberIdSelect"
#memberName>
<mat-autocomplete #memberIdSelect="matAutocomplete">
<mat-option class="no-padding"
[style.opacity]="!member.isActive ? '.5' : '1'"
[disabled]="!member.isActive"
*ngFor="let member of members" [value]="member">
<span class="text-teal-800 user-name-family font-8-em padding-mini-r-l">
{{member.name}} {{member.family}}
</span>
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field class="font-7-em filter-fields pos-rel margin-r-l"
[ngClass]="rtlDirection ? 'float-left' : 'float-right'"
[floatLabel]="'never'">
<mat-icon class="text-light-blue-500 login-icon" matPrefix>search</mat-icon>
<input type="text"
#filterTxt
matInput
placeholder="{{'PROJECT_FILTER.NAME' | translate}}"
autocomplete="off"
tabindex="1">
<button type="button" mat-button *ngIf="filterTxt.value" matSuffix mat-icon-button
aria-label="Clear" (click)="filterTxt.value = ''">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
<button mat-icon-button
[matMenuTriggerFor]="menu"
click-stop-propagation
class="btn-card-add btn-rounded top-full green-gradient mat-elevation-z1 text-white overflow-hide text-weight-normal line-height-30 display-block width-30 height-30"
aria-label="Toggle menu">
<mat-icon>add</mat-icon>
</button>
<mat-menu #menu="matMenu" xPosition="before" class="no-padding menu-width">
<h6 mat-subheader class="font-8-em">{{'FILTER.ADD_FILTER' | translate}}</h6>
<mat-divider></mat-divider>
<a (click)="activeFilterType(item)" mat-menu-item *ngFor="let item of filterTypes">
<span class="font-8-em"
[ngClass]="rtlDirection ? 'float-right' : 'float-left'">
{{item.info.name | translate}}
</span>
<mat-icon *ngIf="item.info.visible"
class="font-full-plus-half-em no-margin margin-t-half text-red-500"
[ngClass]="rtlDirection ? 'float-left' : 'float-right'">
check
</mat-icon>
</a>
</mat-menu>
</div>
</mat-card>
</div>
<div class="pos-rel component-content padding-half" [perfectScrollbar]="scrollConfig" *ngIf="projects" [@listAnimations]="projects.length">
<div class="scrollable-content">
<div class="row center-block font-8-rem" [dir]="rtlDirection ? 'rtl' : 'ltr'">
<div *ngFor="let project of projects"
class="col-xs-12 col-sm-6 col-md-4 col-lg-3 height-220 margin-b-full"
[ngClass]="rtlDirection ? 'float-right' : 'float-left'">
<button mat-icon-button
type="button"
[matMenuTriggerFor]="menu"
click-stop-propagation
class="more-button text-orange-600 transition z-index-1"
aria-label="Toggle menu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu class="no-padding-t-b" #menu="matMenu" [xPosition]="'before'">
<a mat-menu-item>
<mat-icon class="text-red-500">close</mat-icon>
<span>{{'GLOBAL.REMOVE' | translate}}</span>
</a>
</mat-menu>
<a [routerLink]="['/projects/detail', project.id]" class="full-width full-height">
<mat-card class="mat-elevation-z3 full-width full-height padding-half">
<mat-card-header class="margin-b-half height-45 overflow-hide">
<mat-card-title class="font-8-rem text-red-500 no-margin-b padding-mini-r-l">
{{project.name}}
</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-list class="full-width no-padding height-120" [ngClass]="rtlDirection ? 'float-left' : 'float-right'">
<mat-list-item class="list-item height-30 text-green-600">
<mat-icon mat-list-icon class="font-full-em text-center line-height-25">done</mat-icon>
<h4 class="font-8-rem">{{project.completeTasksCount !== undefined ? project.completeTasksCount : 0}}</h4>
<p class="font-7-em no-margin-t-b margin-r-l">{{'PROJECT.COUNT_COMPLETE_TASK' | translate}} </p>
</mat-list-item>
<mat-list-item class="list-item height-30 text-red-600">
<mat-icon mat-list-icon class="font-full-em text-center line-height-25">schedule</mat-icon>
<h4 class="font-8-rem">{{project.remainTasksCount !== undefined ? project.remainTasksCount : 0}}</h4>
<p class="font-7-em no-margin-t-b margin-r-l">{{'PROJECT.COUNT_REMAINING_TASK' | translate}} </p>
</mat-list-item>
<mat-list-item class="list-item height-30 text-cyan-800">
<mat-icon mat-list-icon class="font-full-em text-center line-height-25">person</mat-icon>
<h4 class="font-8-rem">{{project.membersCount !== undefined ? project.membersCount : 0}}</h4>
<p class="font-7-em no-margin-t-b margin-r-l">{{'PROJECT.COUNT_MEMBERS' | translate}} </p>
</mat-list-item>
<mat-list-item class="list-item height-30 text-amber-900">
<mat-icon mat-list-icon class="font-full-em text-center line-height-25">error_outline</mat-icon>
<h4 class="font-8-rem">{{project.issuesCount !== undefined ? project.issuesCount : 0}}</h4>
<p class="font-7-em no-margin-t-b margin-r-l">{{'PROJECT.COUNT_ISSUES' | translate}} </p>
</mat-list-item>
</mat-list>
<section class="padding-mini-r-l full-width clear-both pos-rel top-full-reverse mat-progress-{{getPercentColor(project.percentage)}}">
<span class="padding-b-half text-{{getPercentColor(project.percentage)}}-700"
[ngClass]="rtlDirection ? 'float-left' : 'float-right'">
{{project.percentage}} %
</span>
<mat-progress-bar
color="warn"
[mode]="'determinate'"
[value]="project.percentage">
</mat-progress-bar>
</section>
</mat-card-content>
</mat-card>
</a>
</div>
</div>
</div>
</div>