Reputation: 43057
I am not so into Angular and PrimeNG and I am finding the following problem trying to replicate this PrimeNG table showcase example (the code is provided into the "Source" tab of this page): https://www.primefaces.org/primeng/showcase/#/table
Basically I am try to put this code into a component of my application (then I will adatp it to my use cases).
So I have this component class:
import { Component, OnInit, ViewChild } from '@angular/core';
import { Customer, Representative } from './customer';
import { Table } from 'primeng';
import { CustomerService } from './customerservice';
@Component({
selector: 'app-gestione-ordini',
templateUrl: './gestione-ordini.component.html',
styleUrls: ['./gestione-ordini.component.css']
})
export class GestioneOrdiniComponent implements OnInit {
customers: Customer[];
selectedCustomers: Customer[];
representatives: Representative[];
statuses: any[];
loading: boolean = true;
@ViewChild('dt') table: Table;
constructor(private customerService: CustomerService) { }
ngOnInit() {
this.customerService.getCustomersLarge().then(customers => {
this.customers = customers;
this.loading = false;
});
this.representatives = [
{name: "Amy Elsner", image: 'amyelsner.png'},
{name: "Anna Fali", image: 'annafali.png'},
{name: "Asiya Javayant", image: 'asiyajavayant.png'},
{name: "Bernardo Dominic", image: 'bernardodominic.png'},
{name: "Elwin Sharvill", image: 'elwinsharvill.png'},
{name: "Ioni Bowcher", image: 'ionibowcher.png'},
{name: "Ivan Magalhaes",image: 'ivanmagalhaes.png'},
{name: "Onyama Limba", image: 'onyamalimba.png'},
{name: "Stephen Shaw", image: 'stephenshaw.png'},
{name: "XuXue Feng", image: 'xuxuefeng.png'}
];
this.statuses = [
{label: 'Unqualified', value: 'unqualified'},
{label: 'Qualified', value: 'qualified'},
{label: 'New', value: 'new'},
{label: 'Negotiation', value: 'negotiation'},
{label: 'Renewal', value: 'renewal'},
{label: 'Proposal', value: 'proposal'}
]
}
onActivityChange(event) {
const value = event.target.value;
if (value && value.trim().length) {
const activity = parseInt(value);
if (!isNaN(activity)) {
this.table.filter(activity, 'activity', 'gte');
}
}
}
onDateSelect(value) {
this.table.filter(this.formatDate(value), 'date', 'equals')
}
formatDate(date) {
let month = date.getMonth() + 1;
let day = date.getDate();
if (month < 10) {
month = '0' + month;
}
if (day > 10) {
day = '0' + day;
}
return date.getFullYear() + '-' + month + '-' + day;
}
onRepresentativeChange(event) {
this.table.filter(event.value, 'representative', 'in')
}
}
Then this is the CustomerService service used in the previous component class:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Customer } from './customer';
@Injectable()
export class CustomerService {
constructor(private http: HttpClient) { }
getCustomersSmall() {
return this.http.get<any>('assets/showcase/data/customers-small.json')
.toPromise()
.then(res => <Customer[]>res.data)
.then(data => { return data; });
}
getCustomersMedium() {
return this.http.get<any>('assets/showcase/data/customers-medium.json')
.toPromise()
.then(res => <Customer[]>res.data)
.then(data => { return data; });
}
getCustomersLarge() {
return this.http.get<any>('assets/showcase/data/customers-large.json')
.toPromise()
.then(res => <Customer[]>res.data)
.then(data => { return data; });
}
getCustomersXLarge() {
return this.http.get<any>('assets/showcase/data/customers-xlarge.json')
.toPromise()
.then(res => <Customer[]>res.data)
.then(data => { return data; });
}
}
And this is the related html view page for this component:
<div class="card">
<p-table #dt [value]="customers" [(selection)]="selectedCustomers" dataKey="id" styleClass="p-datatable-customers" [rowHover]="true"
[rows]="10" [showCurrentPageReport]="true" [rowsPerPageOptions]="[10,25,50]" [loading]="loading"
[paginator]="true" currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
[filterDelay]="0" [globalFilterFields]="['name','country.name','representative.name','status']">
<ng-template pTemplate="caption">
<div class="table-header">
List of Cars
<span class="p-input-icon-left">
<i class="pi pi-search"></i>
<input pInputText type="text" (input)="dt.filterGlobal($event.target.value, 'contains')" placeholder="Global Search" />
</span>
</div>
</ng-template>
<ng-template pTemplate="header">
<tr>
<th style="width: 3rem"></th>
<th pSortableColumn="name">Name <p-sortIcon field="name"></p-sortIcon></th>
<th pSortableColumn="country.name">Country <p-sortIcon field="country.name"></p-sortIcon></th>
<th pSortableColumn="representative.name">Representative <p-sortIcon field="representative.name"></p-sortIcon></th>
<th pSortableColumn="date">Date <p-sortIcon field="date"></p-sortIcon></th>
<th pSortableColumn="status">Status <p-sortIcon field="status"></p-sortIcon></th>
<th pSortableColumn="activity">Activity <p-sortIcon field="activity"></p-sortIcon></th>
<th style="width: 8rem"></th>
</tr>
<tr>
<th>
<p-tableHeaderCheckbox></p-tableHeaderCheckbox>
</th>
<th>
<input pInputText type="text" (input)="dt.filter($event.target.value, 'name', 'startsWith')" placeholder="Search by Name" class="p-column-filter">
</th>
<th>
<input pInputText type="text" (input)="dt.filter($event.target.value, 'country.name', 'contains')" placeholder="Search by Country" class="p-column-filter">
</th>
<th>
<p-multiSelect [options]="representatives" placeholder="All" (onChange)="onRepresentativeChange($event)" styleClass="p-column-filter" optionLabel="name">
<ng-template let-option pTemplate="item">
<div class="p-multiselect-representative-option">
<img [alt]="option.label" src="assets/showcase/images/demo/avatar/{{option.value.image}}" width="32" style="vertical-align: middle" />
<span class="p-ml-1">{{option.label}}</span>
</div>
</ng-template>
</p-multiSelect>
</th>
<th>
<p-calendar (onSelect)="onDateSelect($event)" (onClearClick)="dt.filter('', 'date', 'equals')" [showButtonBar]="true" styleClass="p-column-filter" placeholder="Registration Date" [readonlyInput]="true" dateFormat="yy-mm-dd"></p-calendar>
</th>
<th>
<p-dropdown [options]="statuses" (onChange)="dt.filter($event.value, 'status', 'equals')" styleClass="p-column-filter" placeholder="Select a Status" [showClear]="true">
<ng-template let-option pTemplate="item">
<span [class]="'customer-badge status-' + option.value">{{option.label}}</span>
</ng-template>
</p-dropdown>
</th>
<th>
<input pInputText type="text" (input)="onActivityChange($event)" placeholder="Minimum" class="p-column-filter" >
</th>
<th></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-customer>
<tr class="p-selectable-row">
<td>
<p-tableCheckbox [value]="customer"></p-tableCheckbox>
</td>
<td>
<span class="p-column-title">Name</span>
{{customer.name}}
</td>
<td>
<span class="p-column-title">Country</span>
<img src="assets/showcase/images/demo/flag/flag_placeholder.png" [class]="'flag flag-' + customer.country.code" width="30">
<span class="image-text">{{customer.country.name}}</span>
</td>
<td>
<span class="p-column-title">Representative</span>
<img [alt]="customer.representative.name" src="assets/showcase/images/demo/avatar/{{customer.representative.image}}" width="32" style="vertical-align: middle" />
<span class="image-text">{{customer.representative.name}}</span>
</td>
<td>
<span class="p-column-title">Date</span>
{{customer.date}}
</td>
<td>
<span class="p-column-title">Status</span>
<span [class]="'customer-badge status-' + customer.status">{{customer.status}}</span>
</td>
<td>
<span class="p-column-title">Activity</span>
<p-progressBar [value]="customer.activity" [showValue]="false"></p-progressBar>
</td>
<td style="text-align: center">
<button pButton type="button" class="p-button-secondary" icon="pi pi-cog"></button>
</td>
</tr>
</ng-template>
<ng-template pTemplate="emptymessage">
<tr>
<td colspan="8">No customers found.</td>
</tr>
</ng-template>
</p-table>
</div>
It compile correctly but the problem is that when I run my application instead obtain the expected table I am obtaining this error message:
core.js:6228 ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(AppModule)[CustomerService -> CustomerService -> CustomerService]:
NullInjectorError: No provider for CustomerService!
NullInjectorError: R3InjectorError(AppModule)[CustomerService -> CustomerService -> CustomerService]:
NullInjectorError: No provider for CustomerService!
at NullInjector.get (core.js:1085)
at R3Injector.get (core.js:16955)
at R3Injector.get (core.js:16955)
at R3Injector.get (core.js:16955)
at NgModuleRef$1.get (core.js:36329)
at Object.get (core.js:33972)
at getOrCreateInjectable (core.js:5848)
at Module.ɵɵdirectiveInject (core.js:21103)
at NodeInjectorFactory.GestioneOrdiniComponent_Factory [as factory] (gestione-ordini.component.ts:11)
at getNodeInjectable (core.js:5993)
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:41632)
at ZoneDelegate.invokeTask (zone-evergreen.js:398)
at Zone.runTask (zone-evergreen.js:167)
at drainMicroTaskQueue (zone-evergreen.js:569)
Why am I obtaining this error? What could be the problem?
Upvotes: 0
Views: 345
Reputation: 2454
Try adding
@Injectable({provided in: "root"})
To your service class. This will include it in the root injector and make it available to any entity in your application.
Alternatively if you only want this service available to part of your application you need to include it in a NgModule in the provides array
Upvotes: 1