Ng2-table not working with latest Angular2 version - html

I am currently using Angular2 for my application and now I want to add ng2-table to my component.
ng2-Table on Git
I am getting this error and couldn't help but ask:
angular2-polyfills.js:487 Unhandled Promise rejection: Template parse errors:
Can't bind to 'colums' since it isn't a known property of 'ng-table'.
1. If 'ng-table' is an Angular component and it has 'colums' input, then
verify that it is part of this module.
2. If 'ng-table' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA"
to the '#NgModule.schema' of this component to suppress this message.
("
</div>-->
<ng-table [ERROR ->][colums]="columns" [rows]="rows" > </ng-table>
<div class="">
"): DeviceOverviewComponent#18:10 ;
Zone: <root> ; Task: Promise.then ; Value: Error: Template parse errors:(…)
In my html I got this:
<ng-table [columns]="columns" [rows]="rows" > </ng-table>
My Component is this:
import { Component } from '#angular/core';
import { Router } from '#angular/router';
import { DeviceService } from '../services/device.service';
#Component({
selector: 'device-overview',
templateUrl: 'dist/html/deviceoverview.component.html',
providers: [DeviceService],
})
export class DeviceOverviewComponent {
devices: any;
columns: any;
rows: any;
constructor(private deviceService: DeviceService, private router: Router) {
}
loadDevices() {
this.deviceService.getDevices()
.then((data) => {
this.devices = data
this.rows = this.devices
})
}
goToDevice(deviceName: string) {
this.router.navigateByUrl('/devices/' + deviceName)
}
ngOnInit() {
this.columns = [
{ title: "test", name: "id" }]
this.loadDevices();
}
}
And my app.module is this:
import { NgModule } from '#angular/core';
import { LocationStrategy, HashLocationStrategy } from '#angular/common';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { Ng2TableModule } from 'ng2-table/ng2-table';
import { AppComponent } from './components/app.component';
import { DeviceOverviewComponent } from './components/deviceoverview.component'
import { DeviceService } from './services/device.service';
import { routing } from './app.routing';
#NgModule({
imports: [
Ng2TableModule,
BrowserModule,
FormsModule,
HttpModule,
routing,
],
declarations: [
DeviceOverviewComponent,
AppComponent,
],
providers:
[
{provide: LocationStrategy, useClass: HashLocationStrategy},
DeviceService,
],
bootstrap: [AppComponent]
})
export class AppModule { }
Does anybody know anything about the Usage of ng2-table? Or is there a valid alternative, since the demo page/usage documentation is not available by now?
I found some alternatives, but lots of them had their last commit a long time ago, which might be a problem, since I am always using latest Angular2.
Thanks for reading and any hel is appreciated!
EDIT:
I've made it to the next step!
I needed to add
import {CUSTOM_ELEMENTS_SCHEMA} from '#angular/core'
#NgModule({ ...,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
within my app.module.ts
Now I am getting the table header with the "test" column and the ID property of my row data is displayed correctly.
Even the demo from ng2-table didn't have that import.
I guess docs and demos arent made for newbes nowadays. :/

i see a typo in your html:
[colums]="columns"
It should be
[columns]="columns"
You're missing n
Plunker Example (I also tried it on local machine and it works)
You shouldn't use CUSTOM_ELEMENTS_SCHEMA
systemjs.config.js
map: {
...
'ng2-table': 'npm:ng2-table'
},
packages: {
...
'ng2-table': {
defaultExtension: 'js'
}
}

After long time I close this issue.
In my case I have these structure:
src
--app
-- app.module
-- TravelPlan
-- travel-plan.module
-- test.component
So, I was trying put the ng2-smart-table in app.module, but I was wrong. The correct is put in travel-plan.module.

Related

Angular 8: not able to get message from Rest Api

I used following links https://grokonez.com/python/django-angular-6-example-django-rest-framework-mysql-crud-example-part-2-django-server and https://grokonez.com/frontend/django-angular-6-example-django-rest-framework-angular-crud-mysql-example-part-3-angular-client to create a django rest API and angular app that calls this rest.
Considering that I'm new in such kind of development so I created as a first step an App that just displays customers list.
Django rest API is fine working. I tested it with the browser:
But my problem is with the angular app, seems that it's not able to get message with the same URL: http://localhost:8000/customers
Below is my angular code:
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { AppRoutingModule, routingComponents } from './app-routing.module';
import { AppComponent } from './app.component';
import { CustomersListComponent } from './customers-list/customers-list.component';
#NgModule({
declarations: [
AppComponent,
routingComponents,
CustomersListComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { CustomersListComponent } from './customers-list/customers-list.component';
const routes: Routes = [
{ path: 'customers', component: CustomersListComponent },
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
customer.ts
export class Customer {
id: number;
name: string;
age: number;
active: boolean;
}
customer.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class CustomerService {
private baseUrl = 'http://localhost:8000/customers';
constructor(private http: HttpClient) { }
getCustomersList(): Observable<any> {
return this.http.get(`${this.baseUrl}/`);
}
}
customers-list.component.ts
import { Component, OnInit, Input } from '#angular/core';
import { Observable } from 'rxjs';
import { CustomerService } from '../customer.service';
import { Customer } from '../customer';
#Component({
selector: 'app-customers-list',
templateUrl: './customers-list.component.html',
styleUrls: ['./customers-list.component.css']
})
export class CustomersListComponent implements OnInit {
customers: Observable<Customer[]>;
constructor(private customerService: CustomerService) { }
ngOnInit() {
console.log("Hellllllllo from customers-list.component.ts ngOnInit");
this.reloadData();
}
reloadData() {
this.customers= this.customerService.getCustomersList();
}
}
customers-list.component.html
<h1>Customers {{JSON.stringify(this.customers)}}</h1>
<div *ngFor="let customer of customers" style="width: 300px;">
<h2>Hello iii</h2>
<div>
<label>Name: </label> {{customer.name}}
</div>
<div>
<label>Age: </label> {{customer.age}}
</div>
<div>
<label>Active: </label> {{customer.active}}
</div>
</div>
The result that got when calling /customers from the browser is the following:
"Routing and Navigation" message is coming from app.component.html
As you can see message Customers is displayed but everything that corresponds to the variable customers (which is the list of customers) is not displayed.
Has someone an idea what's the main cause of this issue? and how I can fix it?
Thank you in advance
You should subscribe to get the response from the API because http.get returns an observable, observable invokes only when you subscribe to it. try the following method
reloadData() {
this.customerService.getCustomersList().subscribe((res: any) => {
this.customers = res;
});
}
In your service
getCustomersList(): Observable<any> {
return this.http.get(`${this.baseUrl}/`);
}
This function returns an observable
So you should subscribe to it like this to make the request
this.customerService.getCustomersList().subscribe((res: any) => {
this.customers = res;
});
Or in your html file you can add async pipe like this
*ngFor="let customer of customers | async

TypeScript variable seems not to load the value from one file to another

I am following the tutorial here: https://coursetro.com/posts/code/154/Angular-6-Tutorial---Learn-Angular-6-in-this-Crash-Course
I currently have the code up to the section titled Fetching More Data from the API working. In short this is supposed to make a page with a bunch of users accessed through a toy API. The users are listed on a page with some personal information, and each one links to a very basic profile page displaying their details. Up to the section I mentioned above, I am successfully interfacing with the API, getting the users and displaying them and some personal information on the main page.
However, the code in this section is intended to collect an individual user's details and display them on a linked page. In trying to follow the example, my code does produce a page with the right outlines, but the value of the variable user$ and its fields like user$.name don't seem to be loaded by the details component. Where those values are supposed to show up, it's blank.
The app files:
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { UsersComponent } from './users/users.component';
import { DetailsComponent } from './details/details.component';
import { PostsComponent } from './posts/posts.component';
const routes: Routes = [
{
path: '',
component: UsersComponent
},
{
path: 'details/:id',
component: DetailsComponent
},
{
path: 'posts',
component: PostsComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.component.html
<div id="container">
<app-sidebar></app-sidebar>
<div id="content">
<router-outlet></router-outlet>
</div>
</div>
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 { SidebarComponent } from './sidebar/sidebar.component';
import { PostsComponent } from './posts/posts.component';
import { UsersComponent } from './users/users.component';
import { DetailsComponent } from './details/details.component';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
declarations: [
AppComponent,
SidebarComponent,
PostsComponent,
UsersComponent,
DetailsComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
data.service.ts
import { Injectable } from '#angular/core';
import {HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }
getUsers() {
return this.http.get('https://jsonplaceholder.typicode.com/users')
}
getUser(userId) {
return this.http.get('https://jsonplaceholder.typicode.com/users'+userId)
}
getPosts() {
return this.http.get('https://jsonplaceholder.typicode.com/posts')
}
}
users files:
users.component.html
<h1>Users</h1>
<ul>
<li *ngFor="let user of users$">
{{user.name}}
<ul>
<li>{{user.email}}</li>
<li>{{user.website}}</li>
</ul>
</li>
</ul>
users.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Observable } from 'rxjs';
#Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss']
})
export class UsersComponent implements OnInit {
users$: Object;
constructor(private data: DataService) { }
ngOnInit() {
this.data.getUsers().subscribe(
data => this.users$ = data
);
}
}
details files:
details.component.html
<h1>{{ user$.name }}</h1>
<ul>
<li><strong>Username: </strong> {{user$.username}}</li>
<li><strong>Email: </strong> {{user$.email}}</li>
<li><strong>Phone: </strong> {{user$.phone}}</li>
</ul>
details.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Observable } from 'rxjs';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-details',
templateUrl: './details.component.html',
styleUrls: ['./details.component.scss']
})
export class DetailsComponent implements OnInit {
user$: Object;
constructor(private data: DataService, private route: ActivatedRoute) {
this.route.params.subscribe( params => this.user$ = params.id );
console.log(this.route.params);
}
ngOnInit() {
this.data.getUser(this.user$).subscribe(
data => this.user$ = data
);
}
}
I tried logging values to the console, but I don't fully understand how TypeScript works so I don't fully know what I really should expect from these logs. In any case, in the log that I made in the details TypeScript file, it showed an object with no apparent loading errors.
this.route.params is a Observable. I am not sure what you can get by logging it.
I would suggest you add a log when subscribing to a observable and see what kind of data you really get. Like.
this.data.getUser(this.user$).subscribe(
data => {console.log(data);this.user$ = data}
);
#Adem, As Haijin comment, you must "work" a bit in subscribe parameter. The idea is that you subscribe to get the parameter, and, when you have the parameter, you ask about the user. But you need to make in the same step using switchMap
ngOnInit()
{
//You subscribe the param. When you have ask for the user
this.route.params.subscribe( params =>
{
this.user$ = params.id;
//In subscribe you ask for the user
this.data.getUser(this.user$).subscribe(
data => this.user$ = data
)
});
}
Well, really In Angular is better don't subscribe two times else using Rjxs and switchMap
ngOnInit()
{
//You subscribe the params, but you don't want the param
this.route.params.pipe(
switchMap(params =>
{ //you want return the user
return this.data.getUser(params.id)
})
).subscribe(data => this.user$ = data)
}

Routing angular 4/5 hiding components

new to routing with angular 4/5, I am following the angular tutorial on their website.
I have an angular application which I want to be able to have two separate pages. Right now main page is localhost:8870/dr3-interface and I want a new page with new components on localhost:8870/dr3-interface/manage_cycles_instances
My issue is when I click on my link Manage cycles instances it shows all my app.component components and not only the components I decided to show on my /manage_cycles_instances. I tried to hide them using *ngIf but without results. Any ideas?
app.component.html :
<div style="text-align:left">
<h1>{{ title }}</h1>
</div>
<nav>
<a routerLink="/manage_cycles_instances" routerLinkActive="active"> Manage cycles instances</a>
</nav>
<router-outlet></router-outlet>
<div *ngIf="router = '/dr3-interface'">
<h2><d-table></d-table></h2>
</div>
<br/>
<form-upload></form-upload>
<br/>
<list-upload></list-upload>
app-routing.module.ts :
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { DataTableComponent } from './datatable/data-table.component';
const appRoutes: Routes = [
{ path: 'manage_cycles_instances', component: DataTableComponent },
/* TO DO : page error
{ path: '**', component: ... }
*/
];
#NgModule({
imports: [
RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // <-- debugging purposes only
)
],
exports: [
RouterModule
]
})
export class AppRoutingModule {}
app.module.ts :
import { BrowserModule } from '#angular/platform-browser';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import {
//all material modules
} from '#angular/material';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { DataTableComponent } from './datatable/data-table.component';
import { DetailsUploadComponent } from './upload/details-upload/details-upload.component';
import { FormUploadComponent } from './upload/form-upload/form-upload.component';
import { ListUploadComponent } from './upload/list-upload/list-upload.component';
#NgModule({
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
HttpClientModule,
//material modules
],
declarations: [
AppComponent,
DataTableComponent,
DetailsUploadComponent,
FormUploadComponent,
ListUploadComponent
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
Your routes should be this :
const appRoutes: Routes = [
{ path: 'dr3-interface', component: DrThreeComponent, children: [ // I don't know which component to use for this route
{ path: 'manage_cycles_instances', component: DataTableComponent },
]},
];
Because you want to have nested routes, you should make nested routes. Note that your DrThreeComponent should have a router-outlet, since it has children.
You won't need to use conditions in your code, because the router will handle the display of your components.
Explanation :
You start by having an index.html file. It only contains a tag in its body, usually app-root. This tag will be replaced by your bootstraped component, which is usually AppComponent.
If you want to route your application, you will need to use the router. Several steps are required :
1 - Put a router-outlet tag in the component that will route others (here, app component)
2 - Create your routes (you did it, and I corrected it in my answer).
3 - in case of child routes (routes seprated by slashes, like yours), put a router outlet tag in every parent component, and a children property into the corresponding routes.
In your case, if we were to make a tree, this would look like this :
index.html
|
|--app component (with router outlet)
|
|--DrThree component (with router outlet)
|
|--ManageCycles component
So basically, index will show app, then app will show DrThree, then DrThree will show ManageCycles.

Getting the error "No provider for NavController" when trying to pass data from child component to parent component

I'm trying to send data from my home.ts file to the app.component.ts file using EventEmitter and Output. But everytime I reference the home page component in my app.html I get this seemingly random error. When I remove NavController from the constructor in home.ts, the error goes away.
home.ts :
import { Component, EventEmitter, Output } from '#angular/core';
import { NavController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'home.html',
})
export class HomePage {
message : any;
#Output() notify : EventEmitter<Object> = new EventEmitter<Object>();
constructor(public navCtrl: NavController) {
}
ionViewDidLoad(){
this.message = {"Name":"Sid", "Age":17};
this.notify.emit(this.message);
}
}
app.html :
<ion-nav [root]="rootPage"></ion-nav>
<page-home (notify)="getChildData($event)"></page-home>
app.component.ts :
import { Component, ViewChild, ViewChildren } from '#angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { HomePage } from '../pages/home/home';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = HomePage;
constructor(platform: Platform, statusBar: StatusBar, splashScreen:
SplashScreen) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
}
getChildData(message){
console.log(message["Name"]);
console.log(message["Age"]);
}
}
How do I fix this error ? I need to use the NavController so I can't remove it. I want to still be able to send data from the child component to the parent component
The error is pointing out that you should provide the NavController in the providers section somewhere. This section could be in several modules of your application but the general one is the app.module.ts file.
In there you have a providers section in which you can provide services or providers for the Angular dependency injection mechanism to work appropriately.
So my first thougth would be to add the navController in the providers section of your app.module.ts file. This ensures that Angular can resolve the dependency to your NavController. Putting it in the app.module.ts file makes it having the same instance fo your navcontroller all over your application.
#NgModule({
bootstrap: [ AppComponent ],
declarations: [
...
],
imports: [
...
],
exports: [
],
providers: [
...
NavController
]
})
However, since you are using ionic, I would check out a related topic on the following url.
Ionic 2 - Runtime Error No provider for NavController

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