Template parse errors when overriding DataTable component of primeNg - angularjs

I want to override the template of the DataTable component of primeng and this is how my code looks like:
my-datatable.component.ts
import { Component, OnInit, ElementRef, Renderer2, ChangeDetectorRef } from '#angular/core';
import { DataTable, DomHandler } from 'primeng/primeng';
import { ObjectUtils } from '../../../../node_modules/primeng/components/utils/ObjectUtils'
import { ColumnHeaders } from '../../../../node_modules/primeng/components/datatable/datatable'
#Component({
selector: 'my-datatable',
templateUrl: './my-datatable.component.html',
styleUrls: ['./my-datatable.component.scss']
})
export class MyDatatableComponent extends DataTable {
constructor(el: ElementRef, domHandler: DomHandler, renderer: Renderer2, changeDetector: ChangeDetectorRef, objectUtils: ObjectUtils) {
super(el, domHandler, renderer, changeDetector, objectUtils);
console.log('MyDatatableComponent');
}
}
my-datatable.component.html, this file has the same template as of the base component. Idea was to first run and then make modifications
<div [ngStyle]="style" [class]="styleClass" [style.width]="containerWidth" [ngClass]="{'ui-datatable ui-widget':true,'ui-datatable-reflow':responsive,'ui-datatable-stacked':stacked,'ui-datatable-resizable':resizableColumns,'ui-datatable-scrollable':scrollable}">
<div class="ui-datatable-loading ui-widget-overlay" *ngIf="loading"></div>
<div class="ui-datatable-loading-content" *ngIf="loading">
<i class="fa fa-circle-o-notch fa-spin fa-2x"></i>
</div>
<div class="ui-datatable-header ui-widget-header" *ngIf="header">
<ng-content select="p-header"></ng-content>
</div>
<p-paginator [rows]="rows" [first]="first" [totalRecords]="totalRecords" [pageLinkSize]="pageLinks" styleClass="ui-paginator-bottom" (onPageChange)="paginate($event)" [rowsPerPageOptions]="rowsPerPageOptions" *ngIf="paginator && paginatorPosition!='bottom' || paginatorPosition =='both'"></p-paginator>
<div class="ui-datatable-tablewrapper" *ngIf="!scrollable">
<table [class]="tableStyleClass" [ngStyle]="tableStyle">
<thead class="ui-datatable-thead">
<tr *ngIf="!headerColumnGroup" class="ui-state-default" [pColumnHeaders]="columns"></tr>
<ng-template [ngIf]="headerColumnGroup">
<tr *ngFor="let headerRow of headerColumnGroup.rows" class="ui-state-default" [pColumnHeaders]="headerRow.columns"></tr>
</ng-template>
</thead>
<tfoot *ngIf="hasFooter()" class="ui-datatable-tfoot">
<tr *ngIf="!footerColumnGroup" class="ui-state-default" [pColumnFooters]="columns"></tr>
<ng-template [ngIf]="footerColumnGroup">
<tr *ngFor="let footerRow of footerColumnGroup.rows" class="ui-state-default" [pColumnFooters]="footerRow.columns"></tr>
</ng-template>
</tfoot>
<tbody [ngClass]="{'ui-datatable-data ui-widget-content': true, 'ui-datatable-hoverable-rows': (rowHover||selectionMode)}" [pTableBody]="columns"></tbody>
</table>
</div>
<ng-template [ngIf]="scrollable">
<div class="ui-datatable-scrollable-wrapper ui-helper-clearfix" [ngClass]="{'max-height':scrollHeight}">
<div *ngIf="frozenColumns" [pScrollableView]="frozenColumns" frozen="true" [ngStyle]="{'width':this.frozenWidth}" class="ui-datatable-scrollable-view ui-datatable-frozen-view"></div>
<div [pScrollableView]="scrollableColumns" [ngStyle]="{'width':this.unfrozenWidth, 'left': this.frozenWidth}" class="ui-datatable-scrollable-view" [virtualScroll]="virtualScroll" (onVirtualScroll)="onVirtualScroll($event)" [ngClass]="{'ui-datatable-unfrozen-view': frozenColumns}"></div>
</div>
</ng-template>
<p-paginator [rows]="rows" [first]="first" [totalRecords]="totalRecords" [pageLinkSize]="pageLinks" styleClass="ui-paginator-bottom" [alwaysShow]="alwaysShowPaginator" (onPageChange)="paginate($event)" [rowsPerPageOptions]="rowsPerPageOptions" *ngIf="paginator && paginatorPosition!='top' || paginatorPosition =='both'"></p-paginator>
<div class="ui-datatable-footer ui-widget-header" *ngIf="footer">
<ng-content select="p-footer"></ng-content>
</div>
<div class="ui-column-resizer-helper ui-state-highlight" style="display:none"></div>
<span class="fa fa-arrow-down ui-datatable-reorder-indicator-up" style="position: absolute; display: none;"></span>
<span class="fa fa-arrow-up ui-datatable-reorder-indicator-down" style="position: absolute; display: none;"></span>
</div>
Also I have added this new component in the declarations array in the app.module.ts file. So, I know that it is being included, which is the reason why I am getting a parse error.
The errors which I encounter in the console is:
Unhandled Promise rejection: Template parse errors:
Can't bind to 'pColumnHeaders' since it isn't a known property of 'tr'. ("ass="ui-datatable-thead">
<tr *ngIf="!headerColumnGroup" class="ui-state-default" [ERROR ->][pColumnHeaders]="columns"></tr>
<ng-template [ngIf]="headerColumnGroup">
"): ng:///AppModule/CsxDatatableComponent.html#14:74
Can't bind to 'pColumnHeaders' since it isn't a known property of 'tr'. (" <tr *ngFor="let headerRow of headerColumnGroup.rows" class="ui-state-default" [ERROR ->][pColumnHeaders]="headerRow.columns"></tr>
</ng-template>
</thead>
"): ng:///AppModule/CsxDatatableComponent.html#16:100
Can't bind to 'pColumnFooters' since it isn't a known property of 'tr'. ("ass="ui-datatable-tfoot">
<tr *ngIf="!footerColumnGroup" class="ui-state-default" [ERROR ->][pColumnFooters]="columns"></tr>
<ng-template [ngIf]="footerColumnGroup">
"): ng:///AppModule/CsxDatatableComponent.html#20:74
Can't bind to 'pColumnFooters' since it isn't a known property of 'tr'. (" <tr *ngFor="let footerRow of footerColumnGroup.rows" class="ui-state-default" [ERROR ->][pColumnFooters]="footerRow.columns"></tr>
</ng-template>
</tfoot>
"): ng:///AppModule/CsxDatatableComponent.html#22:100
Can't bind to 'pTableBody' since it isn't a known property of 'tbody'. ("datatable-data ui-widget-content': true, 'ui-datatable-hoverable-rows': (rowHover||selectionMode)}" [ERROR ->][pTableBody]="columns"></tbody>
</table>
</div>
"): ng:///AppModule/CsxDatatableComponent.html#25:137
Can't bind to 'pScrollableView' since it isn't a known property of 'div'. ("-helper-clearfix" [ngClass]="{'max-height':scrollHeight}">
<div *ngIf="frozenColumns" [ERROR ->][pScrollableView]="frozenColumns" frozen="true"
[ngStyle]="{'width':this.frozenWid"): ng:///AppModule/CsxDatatableComponent.html#31:41
Can't bind to 'pScrollableView' since it isn't a known property of 'div'. ("ozenWidth}" class="ui-datatable-scrollable-view ui-datatable-frozen-view"></div>
<div [ERROR ->][pScrollableView]="scrollableColumns" [ngStyle]="{'width':this.unfrozenWidth, 'left': this.frozenWidt"): ng:///AppModule/CsxDatatableComponent.html#33:19
Can't bind to 'virtualScroll' since it isn't a known property of 'div'. ("is.unfrozenWidth, 'left': this.frozenWidth}"
class="ui-datatable-scrollable-view" [ERROR ->][virtualScroll]="virtualScroll" (onVirtualScroll)="onVirtualScroll($event)"
[ngClas"): ng:///AppModule/CsxDatatableComponent.html#34:55 ; Zone: <root> ; Task: Promise.then ;
pColumnHeaders, pColumnFooters are all components which are already exported via the DataTableModule. I am unable to figure out how to make these parsing errors go away, I am sure I am missing something.
Any help is much appreciated.
Update:
This is how my app.module.ts looks. I have the DataTableModule, BrowserModule and FormsModule imported. I am able to use the standard primeNg datatable component on my views, just not able to override it.
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
/* PRIME NG */
import {
AutoCompleteModule,
PanelMenuModule,
MenuItem,
MenubarModule,
OverlayPanelModule,
TabViewModule,
ButtonModule,
CodeHighlighterModule,
DropdownModule,
DialogModule,
MultiSelectModule ,
InputTextModule,
TooltipModule,
CheckboxModule,
SplitButtonModule,
RadioButtonModule,
MessagesModule,
ConfirmDialogModule,
ConfirmationService,
AccordionModule,
PanelModule,
FieldsetModule,
CalendarModule,
DataTableModule,
MenuModule,
BreadcrumbModule,
TreeModule,
DomHandler,
ChartModule
} from 'primeng/primeng';
import { ObjectUtils } from '../../node_modules/primeng/components/utils/ObjectUtils';
/* APP-SPECIFIC */
import { WindowRef } from './windowref';
import { routing } from './app.routing';
import { MyDatatableComponent } from './components/my-datatable.component';
#NgModule({
declarations: [
DatatableComponent,
ChartsGraphsComponent,
CsxDatatableComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
routing,
AutoCompleteModule,
BrowserAnimationsModule,
PanelMenuModule,
MenubarModule,
OverlayPanelModule,
TabViewModule,
ButtonModule,
CodeHighlighterModule,
DropdownModule,
MultiSelectModule,
DialogModule,
InputTextModule,
TooltipModule,
CheckboxModule,
SplitButtonModule,
RadioButtonModule,
MessagesModule,
ConfirmDialogModule,
AccordionModule,
PanelModule,
FieldsetModule,
CalendarModule,
DataTableModule,
MenuModule,
BreadcrumbModule,
TreeModule,
ChartModule
],
providers: [
DomHandler,
ObjectUtils
],
bootstrap: [AppComponent]
})
export class AppModule { }

You see this error because the selectors you're trying to use are not exported by their respective modules, because they're part of the internal/private part of the PrimeNG framework.
Importing the DataTableModule will make no difference if the selectors you're trying to use are not exported.
In the case of [pColumnHeaders], defined in datatable.ts by the ColumnHeaders component, you'll see that the ColumnHeaders component is not exported in the DataTableModule definition:
#NgModule({
imports: [CommonModule,SharedModule,PaginatorModule,FormsModule],
exports: [DataTable,SharedModule],
declarations: [DataTable,DTRadioButton,DTCheckbox,ColumnHeaders,ColumnFooters,TableBody,ScrollableView,RowExpansionLoader]
})
export class DataTableModule { }
Source of datatable.ts
For you to be able to use the [pColumnHeaders] selector, the DataTableModule would have to export the ColumnHeaders component like so:
#NgModule({
imports: [CommonModule,SharedModule,PaginatorModule,FormsModule],
exports: [DataTable,SharedModule,ColumnHeaders],
declarations: [DataTable,DTRadioButton,DTCheckbox,ColumnHeaders,ColumnFooters,TableBody,ScrollableView,RowExpansionLoader]
})
export class DataTableModule { }
My guess is that this design is intentional and that you're trying to use 'private' and undocumented selectors that are not part of the API.
The question you have to ask yourself is what it is you're trying to achieve. Chances are that the PrimeNG DataTable API provides the interface to do that.

Related

Filtering don´t work MatTableDataSource - Angular

I made a table with Angular Material, and used MatTableDataSource to filter the data from a search bar. However, although the column titles are rendered, my data is not displayed. Does anyone know what the problem is. I'm using Angular 13 with Json server for testing.
import { Component, OnInit } from '#angular/core';
import { MatTableDataSource } from '#angular/material/table';
import { Patient } from 'src/app/patients/model/patient';
import { PatientsService } from 'src/app/patients/patients.service';
#Component({
selector: 'app-search-bar',
templateUrl: './search-bar.component.html',
styleUrls: ['./search-bar.component.css']
})
export class SearchBarComponent implements OnInit {
patients: Patient[] = []
dataSource = new MatTableDataSource(this.patients)
displayedColumns = ["name", "cpf", "cityFrom", "surgeon"]
constructor(private patientsService: PatientsService) { }
ngOnInit(): void {
this.patientsService.read().subscribe(resp => {
this.patients = resp
})
}
applyFilter(filterValue: string) {
this.dataSource.filter = filterValue.trim().toLowerCase()
}
}
<form class="search-bar">
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>Pesquisar</mat-label>
<span matPrefix class="material-icons icons">search</span>
<input (keyup)="applyFilter ($any($event.target).value)" matInput placeholder="Pesquisar" >
</mat-form-field>
</form>
<div class="div-table">
<table mat-table [dataSource]="dataSource" class="mat-elevation-z4 table">
Name Column
<ng-container matColumnDef="name">
<th class="table-title" mat-header-cell *matHeaderCellDef> Nome </th>
<td mat-cell *matCellDef="let row"> {{row.name}} </td>
</ng-container>
...
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>

Facing multiple error like 'mat-form-field' is not a known element and prevents the web page from loading

I am new to angular and have been learning it for the past few days.
The application contains the following:
App Module
---Layout Module
------ Customer Module (All Customer Component)
------ Table Module
The customer module and table module are feature modules.I have imported the html from table component and modified the details to suit the customer component. But I am facing multiple Error message when the page loads which I have attached at the end of this question. I am not sure why the mat-form-field or error such as datasource are causing error and I am not able to load the page. I am not sure why this error is occuring after its imported (MatFormFieldModule) in the CustomerModule.ts file. Please let me know what I am doing wrong ?
Code for each module and other files
CustomerModule.ts:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { CommonModule } from '#angular/common';
import { CustomerRoutingModule } from './customer-routing.module';
import { EditCustomerComponent } from '../Customer/edit-customer/edit-customer.component';
import { MatInputModule, MatTableModule, MatPaginatorModule, MatFormFieldModule } from '#angular/material';
import { AllCustomerComponent } from '../Customer/all-customer/all-customer.component';
#NgModule({
declarations: [ EditCustomerComponent, AllCustomerComponent],
imports: [
CommonModule,
CustomerRoutingModule,
MatTableModule,
MatFormFieldModule,
MatPaginatorModule,
MatInputModule
]
})
export class CustomerModule { }
AllCustomerComponent.ts
import { Component, OnInit, ViewChild } from '#angular/core';
import { MatPaginator, MatSort, MatTableDataSource } from '#angular/material';
import { Customer } from 'src/app/Models/customer';
import { CustomerService } from '../Service/customer.service';
#Component({
selector: 'app-all-customer',
templateUrl: './all-customer.component.html',
styleUrls: ['./all-customer.component.scss']
})
export class AllCustomerComponent implements OnInit {
displayedColumns = ['Id', 'CustomerName', 'CustomerEmailID', 'CustomerPhNo'];
dataSource: MatTableDataSource<Customer>;
public customers: Customer[] = [];
#ViewChild(MatPaginator) paginator: MatPaginator;
#ViewChild(MatSort) sort: MatSort;
constructor(private customerService: CustomerService) {
this.dataSource = new MatTableDataSource(this.customers);
}
ngOnInit() {
this.customerService.getGetAllCustomers().subscribe(data => {
this.dataSource = new MatTableDataSource(data);
});
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
applyFilter(filterValue: string) {
filterValue = filterValue.trim(); // Remove whitespace
filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
this.dataSource.filter = filterValue;
if (this.dataSource.paginator) {
this.dataSource.paginator.firstPage();
}
}
}
AllCustomerComponent.html
<mat-form-field>
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter" />
</mat-form-field>
<div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="Id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let row">{{ row.Id }}</td>
</ng-container>
<ng-container matColumnDef="FirstName">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let row">{{ row.FirstName }}</td>
</ng-container>
<ng-container matColumnDef="Email">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Email ID</th>
<td mat-cell *matCellDef="let row">{{ row.Email }}</td>
</ng-container>
<ng-container matColumnDef="PhoneNumber">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Phone Number</th>
<td mat-cell *matCellDef="let row">{{ row.PhoneNumber }}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>
CustomerService.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpResponse, HttpErrorResponse } from
'#angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, retry, map } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { HttpHeaderService } from 'src/app/Services/http-header.service';
import { HandleError, HttpErrorHandlerService } from 'src/app/Services/http-
error-handler.service';
#Injectable({
providedIn: 'root'
})
export class CustomerService {
private baseUrl: string = environment.baseUrl + 'Customer/';
private handleError: HandleError;
constructor(
private http: HttpClient,
private httpHeaderService: HttpHeaderService,
private httpErrorHandlerService: HttpErrorHandlerService
) {
this.handleError =
httpErrorHandlerService.createHandleError('customerService');
}
getGetAllCustomers(): Observable<any> {
const url: string = this.baseUrl + 'GetAll';
return this.http.get<any>(url,
this.httpHeaderService.getHttpHeader()).pipe(
retry(environment.retryAttempt),
catchError(this.handleError('getGetAllCustomers', 'Error'))
);
}
}
Full Error Message from browser:
Uncaught Error: Template parse errors:
'mat-form-field' is not a known element:
1. If 'mat-form-field' is an Angular component, then verify that it is part
of this module.
2. If 'mat-form-field' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA'
to the '#NgModule.schemas' of this component to suppress this message. ("
[ERROR ->]<mat-form-field>
<input matInput (keyup)="applyFilter($event.target.value)"
placeholder="Filter" /"):
ng:///CustomerRoutingModule/AllCustomerComponent.html#0:0
Can't bind to 'dataSource' since it isn't a known property of 'table'. ("
<div class="mat-elevation-z8">
<table mat-table [ERROR ->][dataSource]="dataSource" matSort>
<ng-container matColumnDef="Id">
<th mat-header-cell *ma"):
ng:///CustomerRoutingModule/AllCustomerComponent.html#5:19
Can't bind to 'matHeaderRowDef' since it isn't a known property of 'tr'. ("
</ng-container>
<tr mat-header-row [ERROR ->]*matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColu"): ng:///CustomerRoutingModule/AllCustomerComponent.html#25:23
Property binding matHeaderRowDef not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "#NgModule.declarations". ("
</ng-container>
[ERROR ->]<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; col"): ng:///CustomerRoutingModule/AllCustomerComponent.html#25:4
Can't bind to 'matRowDefColumns' since it isn't a known property of 'tr'. ("
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row [ERROR ->]*matRowDef="let row; columns: displayedColumns"></tr>
"): ng:///CustomerRoutingModule/AllCustomerComponent.html#26:16
Property binding matRowDefColumns not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "#NgModule.declarations". ("
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
[ERROR ->]<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
"): ng:///CustomerRoutingModule/AllCustomerComponent.html#26:4
Can't bind to 'pageSize' since it isn't a known property of 'mat-paginator'.
1. If 'mat-paginator' is an Angular component and it has 'pageSize' input, then verify that it is part of this module.
2. If 'mat-paginator' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component. ("
</table>
<mat-paginator [ERROR ->][pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>
"): ng:///CustomerRoutingModule/AllCustomerComponent.html#29:17
Can't bind to 'pageSizeOptions' since it isn't a known property of 'mat-paginator'.
1. If 'mat-paginator' is an Angular component and it has 'pageSizeOptions' input, then verify that it is part of this module.
2. If 'mat-paginator' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component. ("
</table>
<mat-paginator [pageSize]="10" [ERROR ->][pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>
"): ng:///CustomerRoutingModule/AllCustomerComponent.html#29:33
'mat-paginator' is not a known element:
1. If 'mat-paginator' is an Angular component, then verify that it is part of this module.
2. If 'mat-paginator' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message. ("
[ERROR ->]<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>
"): ng:///CustomerRoutingModule/AllCustomerComponent.html#29:2
at syntaxError (compiler.js:2427)
at
I was able to resolve this issue. It seems Visual Studio Code has incorrectly added the import details.
Example: File path is layout-> Customer-> EditCustomerComponent
import { EditCustomerComponent } from './customer/edit-customer/edit-customer.component';
Visual Studio Added -
import { EditCustomerComponent } from './Customer/Edit-customer/edit-customer.component';
The Customer should have been customer Which has c small letter. After changing it started working. Visual Studio Code tends to do it on multiple occasion and I had to manually modify it. I am not sure if its something wrong with my setting.
Thanks for the help :)

Cascading drop down in table using Angular 4 typescript

I am new to angular and developing my very first application using angular 4 and typescript
I want to use Cascading drop-down in table using angular4
Currently, I have been working on it but when I change drop down from the first row it is a binding second level dropdown for all row.
I want to bind the second level drop down of the row from the first level drop down is changed.
I have some idea on my mind to achieve this but I guess It might be a patch so I am very curious to know any proper way of angular to achieve this.
ts file code
import { Component, OnInit, EventEmitter } from '#angular/core';
import { Category } from '../model/Category';
import { SubCategory } from '../model/subCategory';
import { Partner } from '../model/partner';
import { GetdataService } from '../../../../Server/api/Getdata.service';
import { Router } from '#angular/router';
#Component({
templateUrl: 'UploadFile.component.html'
})
export class UploadFileComponent implements OnInit {
AllCategoryList: Category[] = [];
AllSubCategoryList: SubCategory[] = [];
constructor(private _datatask: GetdataService, private _router: Router) { }
onChangeCategory(deviceValue) {
if (deviceValue > 0) {
this._datatask.getAllSubCategory(deviceValue).subscribe(
(data: SubCategory[]) => {
this.AllSubCategoryList = data;
}
);
console.log("from component: " + deviceValue);
}
else
{
//clear dropdown...
this.AllSubCategoryList= [];
}
}
ngOnInit() {
this._datatask.getAllCategory().subscribe(
(data: Category[]) => {
this.AllCategoryList = data;
}
);
this._datatask.getAllPartner().subscribe(
(data: Partner[]) => {
this.AllPartnerList = data;
}
);
}
}
HTML file
<div>
<table width="100%" border="1">
<thead>
<th>Category</th>
<th>SubCategory</th>
<th>Partner</th>
</thead>
<tbody *ngFor="let transaction of transactions">
<tr>
<td>
<select style="Width:100px;" (change)="onChangeCategory($event.target.value)" >
<option value=0>--Select--</option>
<option value="{{item.ID}}" *ngFor="let item of AllCategoryList" [ngValue]="item.ID" >{{item.Category}}</option>
</select>
</td>
<td>
<select style="Width:100px;">
<option value=0>--Select--</option>
<option *ngFor="let item of AllSubCategoryList" [ngValue]="item.ID" >{{item.SubCategory}}</option>
</select>
</td>
<td>
<select style="Width:100px;">
<option value=0>--Select--</option>
<option *ngFor="let item of AllPartnerList" [ngValue]="item.ID" >{{item.PartnerName}}</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
any help will be highly appreciated.
The problem is you needed an array of states... (in the plunker you listed in the comments below).
You can probably apply same to your code in original question.
list-component.ts tweaks
export class CountryListComponent {
states: State[] = [[] as State[],[] as State[],[] as State[]]
onSelect(value,index) {
this.states[index] = this._dataService.getStates().
filter((item)=> item.countryid == value);
}
}
list-component.html tweak
Updated: after this exchange with #GünterZöchbauer :
Use (ngModelChange) over (change)
<select [(ngModel)]="selectedCountry[number].id"
(ngModelChange)="onSelect($event, number)">
Fixed Plunker
I am also faced this problem and finally got a solution using custom pipe.
make a filter in external file like - mycustomfilter.ts
mycustomfilter.ts
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'myCustomFilter',
pure: false
})
export class myCustomFilterPipe implements PipeTransform {
transform(items: any[], field : string, value): any[] {
if (!items) return [];
if (!value || value.length === 0) return items;
return items.filter(it =>
it[field] === value);
}
}
declarations in app module
#NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ App, myCustomFilterPipe],
bootstrap: [ App ]
})
item-order.component.ts
categoryList=[{id:1,name:'Office Stationery'},
{id:2,name:'Grocery'}
];
itemList=[
{id:1,name:'Pen',categoryID:1},
{id:2,name:'A4 Peper',categoryID:1},
{id:3,name:'Oil',categoryID:2},
{id:4,name:'Sugar',categoryID:2}
];
item-order.component.html
<tr *ngFor="let order of o.controls; let i = index" [formGroup]="order" class="form-row">
<td>
<select class="form-control" formControlName="ItemCategoryID">
<option value="">Select</option>
<option *ngFor="let s of categoryList" [ngValue]="s.id">{{s.name}}</option>
</select>
</td>
<td>
<select class="form-control" formControlName="ItemID">
<option value="">Select</option>
<option *ngFor="let s of itemList | myCustomFilter : 'categoryID' : order.value.ItemCategoryID" [ngValue]="s.id">{{s.name}}</option>
</select>
</td>
</tr>

How to pass JSON data to a modal in angular 2

I am trying to pop up a modal in angular 2 that will display a list of people. The source of the list is a JSON file. I think the data is not being properly bound to the table in the modal. I am new to angular 2 and am not sure what I am missing.
Service to read JSON file:
returns-json-array-service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs';
#Injectable()
export class ReturnsJsonArrayService {
constructor(private http: Http) {}
getPeople(): Observable<any> {
return this.http.request('./people.json')
.do( res => console.log('HTTP response:', res))
.map(res => res.json().payload)
.do(console.log);
//.map(res => res.json());
/*return this.http.get('./people.json')
.map((res:Response) => res.json())
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));*/
}
}
SAmple json file: people.json
{
"id": "1",
"name": "David Martinez Ros",
"email": "info#davidmartinezros.com",
"age": "33"
},
{
"id": "2",
"name": "Paco Roberto Corto",
"email": "paco.roberto.corto#gmail.com",
"age": "51"
},
{
"id": "3",
"name": "Silvia Elegante i Latina",
"email": "silvia.elegante.latina#gmail.com",
"age": "30"
}
]
modal-component.ts
import {Component, Input} from '#angular/core';
import {NgbModal, NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
import { Observable } from 'rxjs';
import { ReturnsJsonArrayService } from './returns-json-array.service';
#Component({
selector: 'ngbd-modal-content',
providers: [ReturnsJsonArrayService],
template: `
<div class="modal-header">
<h4 class="modal-title">Hi there!</h4>
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
<div class="modal-body" *ngFor="let person of peopleData | async" >
<p>One fine body…</p>
<table border=1>
<tr>
<td>
<h3>Id: {{ person.id }}</h3>
</td>
<td>
<h3>name: {{ person.name }}</h3>
</td>
<td>
<h3>email: {{ person.email }}</h3>
</td>
<td>
<h3>age: {{ person.age }}</h3>
</td>
<td>
</tr>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="activeModal.close('Close click')">Submit</button>
</div>
`
})
export class NgbdModalContent {
#Input() name;
#Input() peopleData: Observable<Array<any>>;
constructor(public activeModal: NgbActiveModal,private peopleService: ReturnsJsonArrayService) {
this.peopleData = this.peopleService.getPeople();
console.log("AppComponent.data:" + this.peopleData);
}
}
#Component({
selector: 'ngbd-modal-component',
templateUrl: './modal-component.html'
})
export class NgbdModalComponent {
constructor(private modalService: NgbModal) {}
open() {
const modalRef = this.modalService.open(NgbdModalContent);
modalRef.componentInstance.name = 'Barb' ;
console.log("Peopledatra on open():" + modalRef.componentInstance.peopleData);
}
}
modal-component.html
<button class="btn btn-primary" (click)="open()">Assign</button>
this.peopleService.getPeople() returns an observable which is cold to activate it and make it hot you must add a subscribe this.peopleService.getPeople().subscribe() the subscribe will take a success method as the first argument like so:
this.peopleService.getPerople().subscribe(
(json) => {
// do something here with the json
}
)
Once the json is returned you can set it to a property within your components scope like so:
this.peopleService.getPerople().subscribe(
(json) => {
this.json = json;
}
)
That property will then be accessible with in the components template.

Angularjs 2 ng-repeat not working

I am using ng-repeat in angularjs 2 with custom template but it's not working
html
<tr ng-repeat="data in itemList">
<td>{{data.test}}</td>
</tr>
.ts
import {Component, View} from "angular2/core";
#Component({
selector: 'my-app',
templateUrl: 'app/hello.component.html'
})
export class AppComponent {
public itemList = [
{name:"Apple", test:"1"},
{name:"Orange", test:"2"},
{name:"Grapes", test:"3"},
];
}
I don't know what is the problem. It's working in Angularjs 1 but Angularjs 2 not working
You should use *ngFor instead of ng-repeat. There is no ng-repeat with angular2.
Change it as,
<tr *ngFor="let data of itemList">
<td>{{data.test}}</td>
</tr>
DEMO
Here is full syntax of code.
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
template: `
<p>List:</p>
<ul>
<li *ngFor="let item of itemList">
{{ item.name }} {{item.test}}
</li>
</ul>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
public carsList: Array<string>;
public itemList = [
{ name: "Apple", test: "1" },
{ name: "Orange", test: "2" },
{ name: "Grapes", test: "3" },
];
}

Resources