Angular - Can't import a component from a library - html

I'm learning Angular and I decided to create separate generic elements in addition to the main project (in a library) and then import and use them according to my needs.
My problem is due to the fact that I can't import the generic components now... (I can import the Module from the library, but when I try to use my component's selector, Angular warns that the element is unknown to it and doesn't compile the server ).
Generic Component:
(.html)
<p>f-base-screen works!</p>
(.ts)
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'nx-flow-base-screen',
templateUrl: './f-base-screen.component.html',
styleUrls: ['./f-base-screen.component.scss'],
})
export class FBaseScreenComponent implements OnInit {
constructor() {}
ngOnInit(): void {}
}
Library Module:
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FBaseScreenComponent } from './f-base-screen/f-base-screen.component';
#NgModule({
imports: [
CommonModule
],
declarations: [
FBaseScreenComponent
],
exports: [
FBaseScreenComponent
],
})
export class FLibrariesModule {}
f-libraries.ts (exports the module and its components):
export * from './f-libraries.module';
export * from './f-base-screen/f-base-screen.component';
My SharedModule (it's later imported into my app.module):
import { CommonModule } from "#angular/common";
import { NgModule } from "#angular/core";
import { FLibrariesModule } from "#nx-flow/f-libraries";
#NgModule({
imports: [CommonModule, FLibrariesModule],
exports: [CommonModule, FLibrariesModule],
providers: []
})
export class SharedModule {}
App.module.ts:
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { BrowserModule } from '#angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FRestService } from './shared/utils/rest.service';
import { SharedModule } from './shared/shared.module';
#NgModule({
declarations: [AppComponent],
imports: [BrowserModule, AppRoutingModule, HttpClientModule, SharedModule],
exports: [],
providers: [FRestService],
bootstrap: [AppComponent],
})
export class AppModule {}
My Home.component.module.ts (which imports the SharedModule to use the nx-flow-base-screen component):
import { NgModule } from '#angular/core';
import { WelcomeService } from '../../shared/services/flow-services/welcome.service';
import { SharedModule } from '../../shared/shared.module';
import { FRestService } from '../../shared/utils/rest.service';
import { HomeComponent } from './home.component';
#NgModule({
declarations: [HomeComponent],
imports: [SharedModule],
providers: [WelcomeService, FRestService],
bootstrap: [HomeComponent],
})
export class HomeComponentModule {}
My Home.component.html (using the component, the error that appears in the image is the same as angular throws when I compile):
<div>
<span>Home Page</span>
</div>
<nx-flow-base-screen></nx-flow-base-screen>
I already researched and followed tutorials, none of them worked so far. Are there any changes I still need to make to be able to use my component, from the library, within my main project?
If any more files are needed to reach a conclusion, I'll post a print of it.
Error:
apps/flow/src/app/views/home/home.component.html:4:3 - error
NG8001: 'nx-flow-base-screen' is not a known element:
If 'nx-flow-base-screen' is an Angular component, then verify that it is part of this module.
If 'nx-flow-base-screen' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component
to suppress this message.

Related

How to use Angular components from different folder?

Seems like an obvious design decision for me but i can't seem to find any info on how to implement it.
I did the following:
created /pages folder and turned components in to modules for routing
created /components folder for components only
src/app/components/footer/footer.component.ts :
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-footer',
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.css']
})
export class FooterComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
src/app/pages/home/home.component.ts :
import { Component, OnInit } from '#angular/core';
import { TranslateConfigService } from 'src/app/services/translate-config.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private translateConfigService: TranslateConfigService) { }
ngOnInit(): void {
}
}
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { RouterModule } from '#angular/router';
import { HomeRoutes } from './home.routes';
import { TranslateModule } from '#ngx-translate/core';
import { HomeComponent } from './home.component';
import { FooterComponent } from 'src/app/components/footer/footer.component';
#NgModule({
declarations: [
HomeComponent,
FooterComponent,
],
exports: [HomeComponent],
imports: [
CommonModule,
RouterModule.forChild(HomeRoutes),
TranslateModule
]
})
export class HomeModule { }
I didn't import anything explicitly, but when i try to use from /components in some page's html - i get an error saying
Error: src/app/pages/terms/terms.component.html:391:1 - error NG8001: 'app-footer' is not a known element:
1. If 'app-footer' is an Angular component, then verify that it is part of this module.
2. If 'app-footer' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.

Angular 9: Cannot instantiate cyclic dependency

I am reusing a service for HTTP communication which worked fine under Angular 8, but throws the following error under Angular 9:
Error: Cannot instantiate cyclic dependency! HttpService
at throwCyclicDependencyError (core.js:8122)
at R3Injector.hydrate (core.js:17206)
at R3Injector.get (core.js:16960)
at NgModuleRef$1.get (core.js:36337)
at Object.get (core.js:33981)
at getOrCreateInjectable (core.js:5880)
at Module.ɵɵdirectiveInject (core.js:21115)
at NodeInjectorFactory.DashboardComponent_Factory [as factory] (dashboard.component.ts:9)
at getNodeInjectable (core.js:6025)
at instantiateRootComponent (core.js:12788)
at resolvePromise (zone-evergreen.js:798)
at resolvePromise (zone-evergreen.js:750)
at zone-evergreen.js:860
at ZoneDelegate.invokeTask (zone-evergreen.js:399)
at Object.onInvokeTask (core.js:41640)
at ZoneDelegate.invokeTask (zone-evergreen.js:398)
at Zone.runTask (zone-evergreen.js:167)
at drainMicroTaskQueue (zone-evergreen.js:569)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:484)
at invokeTask (zone-evergreen.js:1621)
This is the code of the HTTP service:
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
#Injectable()
export class HttpService {
url: string = 'http://localhost:8000/';
constructor(private httpClient: HttpClient) { }
public getTestCall() {
return this.httpClient.get(this.url + 'test');
}
}
This is one of the components using HTTP service:
import { Component, OnInit } from '#angular/core';
import { HttpService } from 'src/app/services/http.service';
#Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
constructor(private http: HttpService) { }
ngOnInit(): void { }
}
This is my app.module.ts:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpService } from './services/http.service';
import { environment } from 'src/environments/environment';
import { DashboardComponent } from './views/dashboard/dashboard.component';
import { MaterialsComponent } from './views/materials/materials.component';
import { OrdersComponent } from './views/orders/orders.component';
import { CustomersComponent } from './views/customers/customers.component';
import { ModelsComponent } from './views/models/models.component';
import { ProductsComponent } from './views/products/products.component';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
declarations: [
AppComponent,
DashboardComponent,
MaterialsComponent,
OrdersComponent,
CustomersComponent,
ModelsComponent,
ProductsComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [
HttpService,
{ provide: 'BACKEND_API_URL', useValue: environment.backendApiUrl }
],
bootstrap: [AppComponent]
})
export class AppModule { }
The components are referred within the app.component.html using the [routerLink] directive and app-routing.module.ts
Thanks in advance!
I prefer declaring the HTTP Services as:
#Injectable({
providedIn: 'root',
}) and not providing them in any module.
That way the Service is accessible on the whole app from the beginning and probably you won't have error like this.
It would be better If you include your apps modules in the question.
If you have more than one modules:
The problem could be, that the HttpService is provided in more than one of your modules.
In that case:
Solution can be to create a new module: HttpServiceModule:
#NgModule({
providers: [ HttpService ]
})
export class HttpServiceModule {}
After that, you have to delete in all other modules: providers: [ ...HttpService... ]

Why does my Angular app display the path of my html-file and not its contents?

I am starting with Angular. I am creating a very simple App, that uses two components. A default app component and a second component that is used in the html-file of the app component.
However, when running the app (see files below for the relevant files), I get the following output:
App component
./server.component.html
Instead of what is actually in the html-file, in my case:
App component
The server component
Anyone knows what I am doing wrong?
Here is my Module: (app.module.ts)
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
import { ServerComponent } from './server/server.component';
#NgModule({
declarations: [
AppComponent,
ServerComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
The html-file of my main component (app.component.html)
<p>App Coponent</p>
<hr>
<app-server></app-server>
The server component (server/server.component.ts)
import { Component } from '#angular/core';
#Component({
selector: 'app-server',
template: './server.component.html'
})
export class ServerComponent {
}
and, finally, the html-file of the server component (server/server.component.html)
<p>The server component</p>
Change
#Component({
selector: 'app-server',
template: './server.component.html'
})
to
#Component({
selector: 'app-server',
templateUrl: './server.component.html'
})

Angular 2 service not able to resolve all parameters

Hi I am trying this for last two days using http reading local json file ,not sure where the problem is
my service file
import {Injectable} from '#angular/core';
import { Http,Response } from '#angular/http';
import { Observable } from 'rxjs/Observable'
import 'rxjs/add/operator/map'
import 'rxjs/add/operator/catch'
export class AcquirerService{
private _url : string = "agent_output1.json";
constructor(private _http : Http){}
getAcquirer(){
return this._http.get(this._url).subscribe(
(data) => console.log(data)
)
// .map((response:Response) => response.json());
}
my component file
import { Component ,OnInit} from '#angular/core';
import {AcquirerService} from '../services/acquirer.service'
#Component({
selector : 'acquirer-message',
templateUrl: '../templates/acquirer.component.html',
providers :[AcquirerService]
})
export class AcquirerComponent implements OnInit{
acquirer_response ;
constructor(private _acquirerService : AcquirerService){
}
ngOnInit(){
this._acquirerService.getAcquirer();
// .subscribe(resAcquirerData => this.acquirer_response = resAcquirerData);
}
}
The error which i am getting is
metadata_resolver.js:972 Uncaught
SyntaxError {__zone_symbol__error: Error: Can't resolve all parameters for AcquirerService: (?)
my main.ts file
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { enableProdMode } from '#angular/core';
import { environment } from './environments/environment';
import { AppModule } from './app/app.module';
import {HttpModule} from '#angular/http'
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);
my app module file
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule,JsonpModule } from '#angular/http';
import { AppComponent } from './components/app.component';
import {AcquirerComponent} from "./components/acquirer.component";
import {IssuerComponent} from "./components/issuer.component";
#NgModule({
declarations: [
AppComponent,AcquirerComponent,IssuerComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
JsonpModule
],
providers: [],
bootstrap: [AppComponent,HttpModule]
})
export class AppModule { }
any help will be much appreciated I am new to angular
Add AcquirerService into providers
#NgModule({
declarations: [
AppComponent,AcquirerComponent,IssuerComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
JsonpModule
],
providers: [AcquirerService],
bootstrap: [AppComponent,HttpModule]
})
export class AppModule { }
plus add #Injectable() before AcquirerService
#Injectable()
export class AcquirerService{ ... }
In your service file, you imported the Injectable but didn't use it. Put #Injectable() before the service name like this
#Injectable()
export class AcquirerService{
//your code here
}

Can't I use a component defined in a file other than app.component.ts in HTML directly?

I am facing difficulty in using a component defined in a file named navigation.component.ts directly on HTML Page.
The same component works fine if I use it under template of a component defined on app.component.ts.
Contents of app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { NavigationComponent} from './shared/navigation.component';
#NgModule({
imports: [BrowserModule],
declarations: [AppComponent, NavigationComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Contents of navigation.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'navigation',
templateUrl: '/views/shared/navigation.html'
})
export class NavigationComponent {
userName: string = 'Anonymous';
}
Contents of app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'main-app',
template: '<navigation></navigation><h1>{{pageTitle}}</h1>'
})
export class AppComponent {
pageTitle: string = 'Portal 2.0';
}
Contents of index.html
<body>
<main-app></main-app>
</body>
The above works and renders menus on top but when I try to use <navigation> directly (given below) it doesn't render it, doesn't show any errors either.
<body>
<navigation></navigation>
</body>
Am I doing something wrong?
And the bigger question is how I go debugging issues like this?
Yes you can use web components. Add all the components that you want to load to entrycomponents.
Using createCustomElement you can create elements and use their selector anywhere.
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, Injector } from '#angular/core';
import { createCustomElement } from '#angular/elements';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
entryComponents: [AppComponent]
})
export class AppModule {
constructor(private injector: Injector) {
console.log('Elements is loaded: Activation');
this.registerComponent('metro-activation-loader', AppComponent);
}
public ngDoBootstrap(): void {
console.log('Elements is loaded: Activation ngDoBootstrap');
}
// tslint:disable-next-line:no-any
private registerComponent(name: string, component: any): void {
const injector = this.injector;
const customElement = createCustomElement(component, { injector });
customElements.define(name, customElement);
}
}