Angular 4 Component is rendered as empty - html

I am new to Angular, I am trying to define a component and use it in my main page.
The thing is that when using the component in index.html all I can see is my <custom-component></custom-component> empty, nothing inside it.
So what I did is:
in Angular cli: ng generate component custom.
in custom.component.html I have just a text inside paragraph tag.
in index.html I inserted the selector found in custom.component.ts (app-custom) as tag.
in app.module.ts I imported the custom component.
ng serve outputs only app-custom tag without the paragraph tag that should be inside it.
What did I miss?
Update:
Code of my component:
custom.component.html
<p>
component works!
</p>
custom.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-custom',
templateUrl: './custom.component.html',
styleUrls: ['./custom.component.css']
})
export class CustomComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>TestApp</title>
<base href="/">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-custom></app-custom>
</body>
</html>
app.module.ts:
import { CustomComponent } from './custom/custom.component';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { FlexLayoutModule } from '#angular/flex-layout';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent,
CustomComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
BrowserAnimationsModule,
FlexLayoutModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

Try to add exports after declarations => [AppComponent, CustomComponent] ? in app.module. Or create a new cli project with the last version

In NgModule.bootstrap, add your own component.
#NgModule({
declarations: [
AppComponent,
CustomComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [
AppComponent,
CustomComponent
]
})
export class AppModule { }

Try this in index.html add the Appcomponent selector tag and inside Appcomponent template refer your custom component selector and don't forgot to import and declare the custom component in app module and bootstrap the Appcomponent so it renders the app component on load which internally refers your custom component. There are many tutorials outside just start with a single component if you are using AngularCli everything is made easy for you.

Related

Add dynamic loading messages with APP_INITIALIZER

I have an app which do some backend calls before initializing. I have a loading screen for this, which tells the user that something is currently loading. The problem is that I also want to show what is currently loading. If one of the backend calls fails, it should specifically displayed what went wrong. To illustrate the problem, I have programmed a small sample app.
app.module.ts
import { APP_INITIALIZER, NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { MatButtonModule } from '#angular/material/button';
import { MatMenuModule } from '#angular/material/menu';
import { MatTreeModule } from '#angular/material/tree';
import { MatIconModule } from '#angular/material/icon';
import { MatInputModule } from '#angular/material/input';
import { TreeNodeComponent } from './tree-node/tree-node.component';
import { ListElementComponent } from './list-element/list-element.component';
import { HttpClient } from '#angular/common/http';
import { forkJoin, switchMap, tap } from 'rxjs';
import { UserService } from './user.service';
import { ProudctService } from './proudct.service';
#NgModule({
declarations: [
AppComponent,
TreeNodeComponent,
ListElementComponent
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MatButtonModule,
MatMenuModule,
MatTreeModule,
MatIconModule,
MatInputModule
],
providers: [{
provide: APP_INITIALIZER,
multi: true,
deps: [UserService, ProudctService],
useFactory: getUserConfig
}],
bootstrap: [AppComponent]
})
export class AppModule { }
export function getUserConfig(userService: UserService, productService: ProudctService) {
return function () {
switchMap(() => {
const user$ = userService.getUsers();
const product$ = productService.getAllProducts();
return forkJoin([user$, product$]);
})
}
}
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>FocusManagerPlayground</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght#300;400;500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body class="mat-typography">
<app-root>
<div class="splash">Loading User... </div><div *ngIf="loading">Succesfull</div><div *ngIf="!loading">failed</div>
<div class="splash">Loading Product...</div>
</app-root>
<app-loading></app-loading>
</body>
</html>
and here a screenshot how it should looks like:
If the first backend call was successful, on the right of the loading message should be a success icon anf if it fails, there should be a fail icon. As the same by loading the products.
Not sure if your example is what your doing or just meant to illustrate but is there a reason your not having the loading messages in the component? I would put your messages in a component and then separate the calls into a service that is kicked off on initialization. The component can reference the service and then you can use something like flags to update the template.
app.module.ts
export const userFactory = (provider: UserService): (() => Promise<void>) => () => provider.load();
#NgModule({
providers: [
UserService,
{ provide: APP_INITIALIZER, useFactory: userFactory, deps: [UserService], multi: true },
Example Service -- just doing the UserService as an example
#Injectable()
export class UserService {
usersLoading: boolean
usersLoadError: boolean
user: any;
load(): void {
this.usersLoading = true;
this.getData();
}
getData() {
setTimeout(() => {
this.user = { id: 1, name: 'hi' };
this.usersLoading = false;
this.usersLoadError = false;
}, 5000);
}
}
Template -- I don't really like flags but just using here to make a point you could also just check that the user property is truthy.
#Component({
selector: 'hello',
template: `<h1>Hello {{name}}!</h1>
{{userService.usersLoading ? 'Loading' : 'loaded' }}`,
styles: [`h1 { font-family: Lato; }`],
})
export class HelloComponent {
#Input() name: string;
constructor(public userService: UserService) {}
}
Please find a working example here:https://stackblitz.com/edit/angular-tj57g2?file=src/app/user.service.ts

There is nothing displayed in my Angular App

I'm new in web development and i am following this tutorial, and up til i before back-end code i tried to build it but there is nothing in the page, i tried ng serve and ng build (then served it to my local IIS). here are the codes
index.html (build)
<!doctype html>
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<meta charset="utf-8">
<title>NewApp</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<script src="runtime-es2015.js" type="module"></script><script src="runtime-es5.js" nomodule defer></script><script src="polyfills-es5.js" nomodule defer></script><script src="polyfills-es2015.js" type="module"></script><script src="styles-es2015.js" type="module"></script><script src="styles-es5.js" nomodule defer></script><script src="vendor-es2015.js" type="module"></script><script src="vendor-es5.js" nomodule defer></script><script src="main-es2015.js" type="module"></script><script src="main-es5.js" nomodule defer></script></body>
</html>
app-routing.module.ts
import { NgModule, Component } from "#angular/core";
import { RouterModule,Routes } from '#angular/router';
import {AuthGuard} from './helpers/canActivateAuthGuard';
import { LoginComponent } from './components/login/login.component';
import { LogoutComponent } from './components/login/logout.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';
import { UsersComponent } from './components/users/users.component';
import {AppComponent} from './layout/app.component'
const routes: Routes = [
{path: '', redirectTo: '/dashboard', pathMatch: 'full', canActivate: [AuthGuard]},
{path: 'login', component: LoginComponent},
{path: 'logout', component: LogoutComponent},
{path: 'dashboard', component: DashboardComponent},
{path: 'users', component: UsersComponent},
]
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
app.module.ts
import {MatButtonModule} from '#angular/material/button';
import {MatCheckboxModule} from '#angular/material/checkbox'
import {MatInputModule} from '#angular/material/input';
import {MatFormFieldModule} from '#angular/material/form-field';
import {MatSidenavModule, MatSidenav} from '#angular/material/sidenav';
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { AppRoutingModule } from './app-routing.module';
import {HttpClientModule} from '#angular/common/http';
#NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule,
MatButtonModule,
MatCheckboxModule,
MatInputModule,
MatFormFieldModule,
MatSidenavModule,
AppRoutingModule,
HttpClientModule],
})
export class AppModule{}
app.component.html
<div *ngIf="authentication">
<app-head></app-head>
<button type="button" mat-button (click)="drawer.toggle()">
Menu
</button>
<mat-drawer-container class="example-container" autosize>
<mat-drawer #drawer class="example=sidenav" mode="slide">
<app-left-panel></app-left-panel>
</mat-drawer>
<div>
<router-outlet></router-outlet>
</div>
</mat-drawer-container>
</div>
<div *ngIf="!authentication"><app-login></app-login></div>
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'new-app';
}
Your AppComponent is never declared. You are missing the following in the AppModule
#NgModule({
declarations : [AppComponent],
bootstrap: [AppComponent],
imports: [
...
This should have been indicated in your browsers developer tools.
As it was already described here you should add AppComponent to declarations and bootstrap array inside of AppModule
#NgModule({
declarations : [AppComponent],
bootstrap: [AppComponent],
imports: [...]
})
You are also using authentication property inside of *ngIf in app.component.html but this property is not defined inside of app.component.ts
Try to add it to the app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'new-app';
authentication = true;
}
This actually didn't cause any error message in console when I tested it on Stackblitz
It's also described in the tutorial you provided
Basically we will have an authentication property in the component
which will allow us to remove the header and the menu if the user is
not logged in, and instead, show a simple login page.

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'
})

Add context path Angular 2

I want to run my app instead of http://localhost:4200 at http://localhost:4200/pilot/.
I'm trying to change the base href at index.html but I get Uncaught SyntaxError: Unexpected token <
This is my index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>PrimengQuickstartCli</title>
<base href="pilot/"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root>Loading...</app-root>
</body>
</html>
And my 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 { MessagesModule } from 'primeng/primeng';
import { InputTextModule } from 'primeng/primeng';
import { PasswordModule } from 'primeng/primeng';
import { ButtonModule } from 'primeng/primeng';
import { DataTableModule, SharedModule } from 'primeng/primeng';
import { DialogModule } from 'primeng/primeng';
import { CarService } from './service/carservice';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
ButtonModule,
MessagesModule,
InputTextModule,
PasswordModule,
ReactiveFormsModule,
DataTableModule,
SharedModule,
DialogModule
],
providers: [CarService],
bootstrap: [AppComponent]
})
export class AppModule { }
Should I change the folder structure?
I appreciate any help.
At the end with this was enough in my index.html:
<base href="/pilot/">
you cam make use of routing module in angular 2 and redirect the user to /pilot when no path is set in the url
SO you will have code like this in app.routing.ts
{path: '',redirectTo: '/pilot',pathMatch: 'full'},
still need to see if this can be done without routing.

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);
}
}