I created a Directive in Angular7 but when i need to use that it show me this error :
Error: StaticInjectorError(AppModule)[NgForOf -> TemplateRef]:
StaticInjectorError(Platform: core)[NgForOf -> TemplateRef]:
NullInjectorError: No provider for TemplateRef!
Error: StaticInjectorError(AppModule)[NgForOf -> TemplateRef]:
StaticInjectorError(Platform: core)[NgForOf -> TemplateRef]:
I create this directive in SharedModule :
#NgModule({
declarations: [FilderrorComponent, UploadfileComponent, ImageComponent, ValidatePermissionDirective],
imports: [
CommonModule
],
exports: [ FilderrorComponent, UploadfileComponent, ImageComponent, ValidatePermissionDirective]
})
export class SharedModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: SharedModule,
providers: [ FilderrorComponent, UploadfileComponent, ImageComponent , ValidatePermissionDirective]
};
}
}
and this is my Directive:
#Directive({
selector: '[appValidatePermission]'
})
export class ValidatePermissionDirective implements OnInit {
show: boolean;
constructor(private templateRef: TemplateRef<any>,
private viewContainerRef: ViewContainerRef
, private dynamic: DynamicPermissionService) { }
// tslint:disable-next-line:no-input-rename
#Input() AccessName: string;
ngOnInit() {
this.ValidatePemission();
if (this.show) {
this.viewContainerRef.createEmbeddedView(this.templateRef);
} else {
this.viewContainerRef.clear();
}
}
ValidatePemission() {
console.log('AccessName : ', this.AccessName);
const find = this.dynamic.dynamicModel.find(x =>
!! x.actionsVM.find(z => z.actionEnglishName === this.AccessName));
console.log(find);
if (find) {
console.log(true);
this.show = true;
} else {
console.log(false);
this.show = false;
}
}
}
and i define the shareModule in AdminModule :
#NgModule({
declarations: [],
imports: [
SharedModule,
AdminpanelRoutingModule,
],
providers: [Toolkit, { provide: HTTP_INTERCEPTORS, useClass: RequestInterceptor, multi: true }]
})
export class AdminpanelModule { }
and I use Directive in HTML :
<span [appValidatePermission]="CreateRole">
<router-outlet></router-outlet>
</span>
Whats The Problem??? How Can I Solve That?
I think the problem comes from the fact that templateRef is null.
Try intializing it before using it maybe
Related
I am getting this error while while doing npm run serve:ssr
my app.module.ts looks like this:
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
HttpClientModule,
AppRoutingModule,
],
providers: [ProductService,
{provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true}
],
bootstrap: [AppComponent]
})
export class AppModule { }
My home.component.ts looks like this:
constructor(private productService: ProductService) { }
ngOnInit(): void {
this.productService.getHomeData().subscribe(
(data) => {
console.log(data);
},
(error) => {
console.log(error);
}
);
}
my product.service looks like this:
#Injectable()
export class ProductService {
getHomeData(): Observable<any> {
return "this.data";
}
}
Kindly help me fix this issue
ERROR TypeError: this.productService.getHomeData is not a function
at HomeComponent.ngOnInit
i have this config for my site :
import { InjectionToken } from '#angular/core';
import { HttpHeaders } from '#angular/common/http';
export let APP_CONFIG = new InjectionToken<IAppConfig>('app.config');
export interface IAppConfig {
apiEndpoint: string;
headersOptions: HttpHeaders;
}
export const AppConfig: IAppConfig = {
apiEndpoint: 'https://localhost:44354/',
headersOptions : new HttpHeaders({ 'Content-Type': 'application/json' }),
};
and i need use the core.module for using the config :
#NgModule({
declarations: [],
imports: [
CommonModule,
ToastrModule.forRoot()
],
exports: [],
providers: [
{
provide: APP_CONFIG,
useValue: AppConfig,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: RequestInterceptor, multi: true
}
],
})
export class CoreModule {
constructor( #Optional() #SkipSelf() core: CoreModule) {
if (core) {
throw new Error("CoreModule should be imported ONLY in AppModule.");
}
}
}
i using the core.module in app.module .
this my app.module :
#NgModule({
declarations: [
AppComponent,
TopHeaderComponent
],
imports: [
BrowserModule,
HttpClientModule,
SharedModule,
ReactiveFormsModule,
AppRoutingModule,
ToastrModule.forRoot(),
BrowserAnimationsModule,
FormsModule,
CoreModule,
NgZorroAntdModule
],
providers:[{ provide: NZ_I18N, useValue: en_US }],
bootstrap: [AppComponent]
})
export class AppModule { }
now i need to use the AppConfig in my service :
constructor(httpClient: HttpClient, #Inject(APP_CONFIG) private appConfig: IAppConfig) {
super(httpClient);
}
but it show me this error :
Uncaught (in promise): NullInjectorError: StaticInjectorError(AppModule)[[object Object]]:
whats the problem ? how can i solve this problem???
Modify your core module like the following (Remove multi: true)
#NgModule({
declarations: [],
imports: [
CommonModule,
ToastrModule.forRoot()
],
exports: [],
providers: [
{
provide: APP_CONFIG,
useValue: AppConfig //multi: true -> Remove here
},
{
provide: HTTP_INTERCEPTORS,
useClass: RequestInterceptor,
multi: true
}
],
})
export class CoreModule {
constructor( #Optional() #SkipSelf() core: CoreModule) {
if (core) {
throw new Error("CoreModule should be imported ONLY in AppModule.");
}
}
}
Then you can inject in your service as below:
#Injectable()
export class MainService {
constructor(#Inject(APP_CONFIG) private appConfig: IAppConfig) { }
getEndPoint(): string {
alert(this.appConfig.apiEndpoint);
return this.appConfig.apiEndpoint;
}
}
Stackblitz Here
Code example
Third party library
#Module({
providers: [AService]
exports: [AService]
})
export class AModule {
}
#Module({
imports: [AModule],
providers: [BService]
exports: [BService]
})
export class BModule {
}
My code
#Module({
imports: [BModule],
providers: [CService]
})
export class CModule {
}
Question
How can I override/replace the AService provider from my code? (without third party library patching)
Following on from my comment, this is how you would go about making a dynamic module with a dynamic provider
export interface ProviderInterface {
handle(): void;
}
#Injectable()
class SomeHandlingProvider {
constructor(#Inject('MY_DYNAMIC_PROVIDER') private readonly dynamicProvider: ProviderInterface) {}
handle(): void {
this.dynamicProvider.handle();
}
}
#Module({})
export class AModule {
public static forRoot(provider: ProviderInstance): DynamicModule {
return {
module: AModule,
providers: [
{
provide: 'MY_DYNAMIC_PROVIDER',
useClass: provider,
},
SomeHandlingProvider,
],
};
}
}
Then you can use like this
class GenericDynamicProviderExample implements ProviderInterface {
handle(): void {
console.log('hello');
}
}
#Module({
imports: [
AModule.forRoot(GenericDynamicProviderExample),
],
})
export class BModule {}
Im creating a unit test for my confirmation modal that uses MatDialog. my first test is a basic test that the component should be created. here is my code for the spec file.
import { ComponentFixture, TestBed, async } from '#angular/core/testing';
import { PocitConfirmationModalComponent } from './confirmation-modal.component';
import { MatDialogRef, MAT_DIALOG_DATA } from '#angular/material';
import { CommonModule } from '#angular/common';
import { PortalModule } from '#angular/cdk/portal';
import { MaterialModule } from 'src/app/core/material/material.module';
import { BrowserDynamicTestingModule } from '#angular/platform-browser-dynamic/testing';
class MatDialogRefStub {
close(param: string) {}
}
describe('PocitConfirmationModalComponent', () => {
let component: PocitConfirmationModalComponent;
let fixture: ComponentFixture<PocitConfirmationModalComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
CommonModule,
MaterialModule,
PortalModule
],
declarations: [PocitConfirmationModalComponent],
providers: [
{ provide: MatDialogRef, useClass: MatDialogRefStub },
{ provide: MAT_DIALOG_DATA, useValue: {} },
]
}).overrideModule(BrowserDynamicTestingModule, {
set: {
entryComponents: [ PocitConfirmationModalComponent ],
}
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PocitConfirmationModalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
this is the component file that I want to test.
import { Component, OnInit, Inject, ViewEncapsulation } from '#angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '#angular/material';
import { ComponentPortal } from '#angular/cdk/portal';
#Component({
selector: 'pocit-confirmation-modal',
templateUrl: './confirmation-modal.component.html',
styleUrls: ['./confirmation-modal.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class PocitConfirmationModalComponent implements OnInit {
portal: ComponentPortal<any>;
constructor(
public dialogRef: MatDialogRef<PocitConfirmationModalComponent>,
#Inject(MAT_DIALOG_DATA) public data: any,
) {
this.portal = new ComponentPortal(this.data.component);
}
ngOnInit() {
}
action(type: string) {
this.dialogRef.close(type);
}
}
after all of these I got this error after running the test.
Error: No component factory found for undefined. Did you add it to #NgModule.entryComponents?
I already added it to entryComponents but still got this error.
//your public data:any model, eg:
const model: any = {
ActionButton: 'Delete',
SupportingText: 'Are you sure?',
};
then in providers:
providers: [
{
provide: MAT_DIALOG_DATA,
useValue: model
}
]
i have i service which i use to load a list of module :
#Injectable()
export class MyService {
public allowedModules: any = this.modulesFilter();
constructor() {
}
public modulesFilter() {
const testPef = true;
const modulesList= [];
if (testPef === true) {
modulesList.push(MyFirstModule);
} else {
modulesList.push(MySecondModule);
}
return modulesList;
}
}
then in my module file , i want to use it like this :
#NgModule({
imports: [
CommonModule,
MyService.allowedModules // THIS IS WRONG
],
declarations: [],
providers: [
MyService
],
exports: [
]
})
export class MyModule { }
Of course it's wrong as i need to not access directly to my service
Suggestions?
you achieve that using lazyLoading
export class LoadGuard implements CanLoad {
constructor(private myService : MyService , private router: Router) {
}
canLoad(route: Route): boolean {
if (this.myService.canBeLoaded()) {
return true;
} else {
return false;
}
}
{
path: 'test',
loadChildren: 'app/test/test.module#TestModule',
canLoad: [LoadGuard]
},
You can use canLoad guard along with LazyLoading. Your service can be called from canLoad