I have created a ngModel and ngchange which binds to the json array in the ts file and shows its contents.
There should be already the first entry selected and its content shown when the page loads. I want to show the default dropdown value before it is selected and show its contents. As of now only blank screen is there on loading and when i select the drop down then content loads.
I am trying to just show the default content first and then if the user clicks it then it should change.
App.component.html
'''
<div>
Select Product :
<select [(ngModel)]="ProductHeader.name" (ngModelChange)="SearchProduct(ProductHeader.name)">
<option *ngFor="let prod of ProductHeader">{{prod.name}} </option>
</select>
<div *ngIf="ProductHeader.name">
<h5>You have selected: {{ProductHeader.name}} Product </h5>
</div>
</div>
<div>
<h4>Product Details:</h4>
<table class="TFtable">
<tr>
<th>Name</th>
<th>Store</th>
<th>Price</th>
<th>Model</th>
</tr>
<tr *ngFor="let Prod of ProductDetails">
<td>{{Prod.title}}</td>
<td>{{Prod.store}}</td>
<td>{{Prod.price}}</td>
<td>{{Prod.model}}</td>
</tr>
'''
App.component.ts
'''
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-anya',
templateUrl: './anya.component.html',
styleUrls: ['./anya.component.css']
})
export class AnyaComponent implements OnInit {
public ProductDetails: any = [];
//filter product details on name and return productDetails object.
public ProductHeader: any =
[{ name: 'Hp' }, { name: 'Dell' }, { name: 'Lenovo' }];
stringifiedData: any;
data: any;
stringData: any;
parsedJson: any;
ngOnInit() {
this.stringifiedData = JSON.stringify(this.Products);
console.log("With Stringify :", this.stringifiedData);
// Parse from JSON
this.parsedJson = JSON.parse(this.stringifiedData);
console.log("With Parsed JSON :", this.parsedJson);
}
public Products = [
{ Name: 'Hp', title: 'HP ENVY Laptop - 15t touch', price: '1099', store: 'Best Buy', model: '15-BS013DX' },
{ Name: 'Dell', title: 'Dell Laptop', price: '700', store: 'Amazon', model: 'I7378-3000SLV-PUS' },
{ Name: 'Lenovo', title: 'Lenovo Touch-Screen Laptop', price: '670', store: 'Target', model: '81A40025US' },
{ Name: 'Hp', title: 'HP OfficeJet Pro 6978 All-in-One Printer', price: '100', store: 'Target', model: 'T0F29A#B1H' },
{ Name: 'Hp', title: 'HP Laptop - 17t touch ', price: '420', store: 'Target', model: '1EZ78AV_1' },
{ Name: 'Dell', title: 'Dell - XPS 27" Touch-Screen All-In-One', price: '670', store: 'Target', model: 'BBY-311C3FX' },
{ Name: 'Dell', title: 'Dell - Inspiron 21.5" Touch-Screen All-In-One', price: '469.90', store: 'Target', model: 'I3265-A067BLK-PUS' },
{ Name: 'Lenovo', title: 'Lenovo - 520-24AST 23.8" Touch-Screen All-In-One', price: '679.99', store: 'Target', model: 'F0D3000EUS' },
{ Name: 'Dell', title: 'Dell - XPS 2-in-1 13.3" Touch-Screen Laptop', price: '1199.99', store: 'Target', model: 'XPS9365-7086SLV-PUS' }
];
constructor() {
this.getProducts();
}
getProducts() {
console.log("getProducts");
return this.ProductHeader;
}
*Search products searches the name and displays the value*
SearchProduct(name: string) {
let obj = this.Products.filter(m => m.Name == name);
this.ProductDetails = obj;
return this.ProductDetails;
}
}
**Do check how to select the default dropdown value**
'''
Sorry, I had to refactor your code a little in order to make it work properly.
HTML
Hint 1
When you use [(ngModel)]
connect it to a separate variable where you can read from and write into. I added selectedProductModel
for this. When you now select a ProductModel this object will be put into selectedProductModel
and you can then call searchProduct()
without the need of handing in any further value.
Hint 2
An option in select must have a value in order to make it work. That's why I added [ngValue]
.
Here is your refined HTML.
<div>
Select Product :
<select [(ngModel)]="selectedProductModel" (ngModelChange)="searchProduct()">
<option *ngFor="let productModel of productModels" [ngValue]="productModel">{{productModel.name}}</option>
</select>
<div *ngIf="selectedProductModel && selectedProductModel.name.length > 0">
<h5>You have selected: {{selectedProductModel.name}} Product </h5>
</div>
</div>
<div>
<h4>Product Details:</h4>
<table class="TFtable">
<tr>
<th>Name</th>
<th>Store</th>
<th>Price</th>
<th>Model</th>
</tr>
<tr *ngFor="let prod of productDetails">
<td>{{prod.title}}</td>
<td>{{prod.store}}</td>
<td>{{prod.price}}</td>
<td>{{prod.model}}</td>
</tr>
</table>
</div>
TS
Hint 3
Classes start with an upper case letter, but variables always start with a lower case letter. The same goes for any method, they always start with a lower case letter. And they should always have a return value assigned, even if it is void
.
Hint 4
Try to define a model you can work with. This ways TypeScript can warn you when you try to access a field that does not exist.
Here is your refactored TS-File.
import { Component, Input, OnInit } from '@angular/core';
// an object that represents a product detail.
class ProductDetails {
constructor(
public name: string,
public title: string,
public price: string,
public store: string,
public model: string
) {
}
}
// an object that represents the product model
class ProductModel {
constructor(
public name: string
) {
}
}
@Component({
selector: 'app-anya',
templateUrl: './anya.component.html',
styleUrls: ['./anya.component.css']
})
export class AnyaComponent implements OnInit {
// a list of product models
public productModels: Array<ProductModel> = [
new ProductModel('Hp'),
new ProductModel('Dell'),
new ProductModel('Lenovo')];
// the currently selected product model.
// It is preset with the first product model of the list.
selectedProductModel = this.productModels[0];
// the list of product details. It gets filled by the `searchProduct()` method.
productDetails: any[] = [];
stringifiedData: any;
data: any;
stringData: any;
parsedJson: any;
// your list of product details
public products = [
new ProductDetails('Hp', 'HP ENVY Laptop - 15t touch', '1099', 'Best Buy', '15-BS013DX'),
new ProductDetails('Dell', 'Dell Laptop', '700', 'Amazon', 'I7378-3000SLV-PUS'),
new ProductDetails('Lenovo', 'Lenovo Touch-Screen Laptop', '670', 'Target', '81A40025US'),
new ProductDetails('Hp', 'HP OfficeJet Pro 6978 All-in-One Printer', '100', 'Target', 'T0F29A#B1H'),
new ProductDetails('Hp', 'HP Laptop - 17t touch ', '420', 'Target', '1EZ78AV_1'),
new ProductDetails('Dell', 'Dell - XPS 27" Touch-Screen All-In-One', '670', 'Target', 'BBY-311C3FX'),
new ProductDetails('Dell', 'Dell - Inspiron 21.5" Touch-Screen All-In-One', '469.90', 'Target', 'I3265-A067BLK-PUS'),
new ProductDetails('Lenovo', 'Lenovo - 520-24AST 23.8" Touch-Screen All-In-One', '679.99', 'Target', 'F0D3000EUS'),
new ProductDetails('Dell', 'Dell - XPS 2-in-1 13.3" Touch-Screen Laptop', '1199.99', 'Target', 'XPS9365-7086SLV-PUS')
];
constructor() {
}
ngOnInit(): void {
this.stringifiedData = JSON.stringify(this.products);
console.log('With Stringify :', this.stringifiedData);
// Parse from JSON
this.parsedJson = JSON.parse(this.stringifiedData);
console.log('With Parsed JSON :', this.parsedJson);
// fire the search method. As productDetails is already preset with the
// first product model, your drowpdown has a selection and the result is shown.
// this is what you were looking for.
this.searchProduct();
}
searchProduct(): void {
this.productDetails = this.products.filter(productDetail => productDetail.name === this.selectedProductModel.name);
}
}