I'm pulling a list of items and then populate it into a drop down. What i want to achieve is when i select a product, its price should be populated in the quantity textbox.
<ion-item>
<ion-label>Item</ion-label>
<ion-select (ionChange)="getProduct()" [(ngModel)]="product">
<ion-option [value]="item.product" *ngFor="let item of items">{{item.product}}</ion-option>
</ion-select>
</ion-item>
<ion-item>
<ion-label>Available</ion-label>
<ion-input type="number" [(ngModel)]="quantity"></ion-input>
</ion-item>
JS
items:any;
product:any;
available:any;
quantity:any;
constructor(public navCtrl: NavController, public navParams: NavParams) {
this.items=[
{
"product": "Ideal Milk",
"quantity": '5'
},
{
"product": "Indome",
"quantity": '1'
},
{
"product": "Corn Flakes",
"quantity": '20'
},
{
"product": "Digestive Biscuit",
"quantity": '12'
}
]
}
getProduct(){
}
}
i'm trying to write a function getProduct() which will check for the product selected and the populate in it in the quantity textbox, thats what i want to achieve.
ion-select is binded to product and ion-input to quantity so all you need to do is update quantity when ion-select is changed.
1) Just renamed getProduct() to onSelectValueChange() to be more clear.
2) When product changes onSelectValueChange is fired. Update this.quantity inside onSelectChange(). New value of quantity should automatically reflect ion-input.
.html
<ion-item>
<ion-label>Item</ion-label>
<ion-select (ionChange)="getProduct()" [(ngModel)]="product">
<ion-option [value]="item.product" *ngFor="let item of items">{{item.product}}</ion-option>
</ion-select>
</ion-item>
<ion-item>
<ion-label>Available</ion-label>
<ion-input type="number" [(ngModel)]="quantity"></ion-input>
</ion-item>
.ts
items:any;
product:any;
available:any;
quantity:any;
constructor(public navCtrl: NavController, public navParams: NavParams) {
this.items=[
{
"product": "Ideal Milk",
"quantity": '5'
},
{
"product": "Indome",
"quantity": '1'
},
{
"product": "Corn Flakes",
"quantity": '20'
},
{
"product": "Digestive Biscuit",
"quantity": '12'
}
]
}
onSelectValueChange(){
this.quantity = this.items.find((element)=>element.product=== this.product).quantity
}
}
Related
I have an object like below. I need to render all the subcategoryList names to an Angular HTML template as single line. I use this kind of solution print array in a single line: someObject.languages.join(' , '). What type of method can I use for this? I can't use *ngFor because it will render separate line for each object item.
{
firstName: " Hello",
lastName: "World",
category: [{
catId: "1",
catName: "SomeCat"
subcategoriesList: [{
subcatId: "5",
subcatName: "SubSomeCat"
},
{
subcatId: "6",
subcatName: "SubSomeCat1"
}
]
}, {
catId: "2",
catName: "SomeCat2"
subcategoriesList: [{
subcatId: "9",
subcatName: "SubSomeCat"
},
{
subcatId: "10",
subcatName: "SubSomeCat1"
}
]
}]
}
Either you can change the structure to a more flattened way. Or you can use span or inline div's.
<span *ngFor="let category of data.category">
<span *ngFor="let subcategory of category.subcategoriesList">
{{subcategory.subCatName}}
</span>
</span>
From what I understood, you want all sub-catgeory names as single string in HTML. You can use angular pipe to transform the data before displaying it on UI.
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'categoryNames'
})
export class CategoryNamesPipe implements PipeTransform {
public transform(obj: unknown): any {
return category
.map(list =>
list.subcategoriesList.map(subCatgeory => subCatgeory.name).join(', ')
)
.join(', ');
}
}
HTML:
<span> {{fullCatgeoryObj | categoryNames}}</span>
As Arcteezy mentioned it can be done with a hack, By default DIV render as display:block and SPAN as display:inline.
----------------------------USING SPAN--------------------------
<br>
<span *ngFor="let category of myData.category">
<span *ngFor="let subcategory of category.subcategoriesList">
{{subcategory.subcatName}}
</span>
</span>
<br>
----------------------------USING DIV------------------
<BR>
<div *ngFor="let category of myData.category" style="float:left">
<div *ngFor="let subcategory of category.subcategoriesList" style="float:left">
{{subcategory.subcatName}}
</div>
</div>
STACKBLITZ DEMO
I am seeking the below result with nested JSON. I am not able to retrive/call keys and values in template dynamically. Refrence link is attached for detail veiw
Angular Code
let checklist = {
"CS": [
{
"id": "1",
"name": "A"
},
{
"id": "2",
"name": "B"
},
{
"id": "3",
"name": "C"
}
],
"Comment": [
{
"id": "1",
"name": "D"
},
{
"id": "2",
"name": "E"
},
{
"id": "3",
"name": "F"
}
]
}
<div *ngFor="let item of Checklist | Key">
{{key}}
<div>{{item}}</div>
</div>
Desired Result
Use keyvalue pipe to loop over Objects within template, Use some css to modify the display but a code like below will serve your need.
<div *ngFor="let item of checklist | keyvalue">
<div>
{{item.key}}
</div>
<div>
<p *ngFor="let eachValue of item.value">
{{eachValue.name}}
</p>
</div>
</div>
https://stackblitz.com/edit/angular-jgwk8n?file=src%2Fapp%2Fapp.component.html
Edit
For angular version < 6, keyvalue pipe doesn't exist. You can create your own custom pipe, maybe like:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'customKeyvalue',
pure: true // keyvalue pipe is actually impure, which means this value would be false
})
export class CustomKeyvaluePipe implements PipeTransform {
transform(inputOb: any): any {
let returnVal = [];
for (let eachKey in inputOb) {
returnVal.push({key: eachKey, value: inputOb[eachKey]})
}
return returnVal
}
}
Now in case your Object changes dynamically without changing its original reference then you would have to make the above pipe as impure (pure: false). This has a downside of being triggered in every change detection.
https://stackblitz.com/edit/angular-jgwk8n?file=src%2Fapp%2Fapp.component.html
You can use Object.keys to get the keys of the object.
This is your component:
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public checklist: any;
public ObjectKeys = Object.keys;
name = 'Angular';
ngOnInit() {
this.checklist = {
"CS": [
{
"id": "1",
"name": "A"
},
{
"id": "2",
"name": "B"
},
{
"id": "3",
"name": "C"
}
],
"Comment": [
{
"id": "1",
"name": "D"
},
{
"id": "2",
"name": "E"
},
{
"id": "3",
"name": "F"
}
]
};
}
}
This is the HTML:
<table border="1">
<tbody>
<tr *ngFor="let key of ObjectKeys(checklist)">
<td colspan="2" style="border-right-style: solid; border-width: 1px;">
{{ key }}
</td>
<td>
<div *ngFor = "let entry of checklist[key]">
{{ entry.name }}
</div>
</td>
</tr>
</tbody>
</table>
This is the result:
You can add CSS to make it look better, but you get the gist now :)
This is the StackBlitz link which you can edit.
The trick here is to use the display: inline-block and vertical-align: top.
It's similar to xyz example.
<div *ngFor="let item of checklist | keyvalue" >
<div style="display:inline-block;">
{{item.key}}
</div>
<div style="display:inline-block;vertical-align: top;">
<div *ngFor="let eachValue of item.value" >
{{eachValue.name}}
</div>
</div>
</div>
Example: https://angular-hzuexu.stackblitz.io
I have a GET method that returns the following JSON on route localhost:3000/documents
[{
"id": "5b48bffc644fca001419769c",
"names": [{
"name": "bob"
},
{
"name": "stan"
}
],
"cities": [{
"city": "London"
},
{
"city": "Madrid"
}
]
}]
I want to concatenate all the names and cities and display them inside HTML tags with Angular.
<p> id </p>
<p> concatenated names here </>
<p> concatenated cities here </>
Is it possible to access documents and concatenate the array values using ngFor?
I have the following component:
import {Component, OnInit} from '#angular/core';
import {DocumentService} from '../services/document.service';
import {Document} from './document.model';
#Component({
selector: 'app-document',
templateUrl: './document.component.html',
styleUrls: ['./document.component.css']
})
export class DocumentComponent implements OnInit {
documents: Document[];
constructor(private documentService: DocumentService) {
}
ngOnInit() {
this.getDocuments();
}
getDocuments(): void {
this.documentService.getDocuments()
.subscribe(documents => this.documents = documents);
}
}
And the following service:
import {Injectable} from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import {Document} from '../document/document.model';
#Injectable({providedIn: 'root'})
export class DocumentService {
private urlDocuments = 'localhost:3000/documents';
constructor(private http: HttpClient) {
}
getDocuments() {
return this.http.get<Document[]>(this.urlDocuments);
}
}
My document model is:
export class Document {
public _id: string;
public names: [{ name: string }];
public cities: [{ city: string }];
constructor(_id: string, names: [{ name: string }],
cities: [{ city: string }]]) {
this._id = _id;
this.cities=cities;
this.names= name;
}
}
I have the solution, but you need to modify your object.
You have to override toString method for cities and names in your model:
test= [{
"id": "5b48bffc644fca001419769c",
"names": [{
"name": "bob",
toString: function(){return this.name;}
},
{
"name": "stan",
toString: function(){return this.name;}
}
],
"cities": [{
"city": "London",
toString: function(){return this.city;}
},
{
"city": "Madrid",
toString: function(){return this.city;}
}
]
}];
HTML section will be look like:
<div *ngFor="let t of test">
<p> {{t.id}}</p>
<p> {{t.names.join(",")}}</p>
<p> {{t.cities.join(",")}} </p>
</div>
Output:
5b48bffc644fca001419769c
bob,stan
London,Madrid
Assume your documents data is getting no problem from server, then try this HTML code below:
<div *ngFor="let d of documents">
<p>Id: {{d.id}}</p>
<p>Names: <span *ngFor="let dd of d.names">{{dd.name}},</span></p>
<p>Cities: <span *ngFor="let dd of d.cities">{{dd.city}},</span></p>
</div>
You just need to use an *ngFor in order to iterate over the documents and then two *ngFors for iterating over the names and the cities like this (StackBlitz Demo):
ts:
documents = [{
"id": "5b48bffc644fca001419769c",
"names": [{"name": "bob"},{"name": "stan"}],
"cities": [{"city": "London"},{"city": "Madrid"}]
},{
"id": "5b48bffc644fca001419769cde",
"names": [{"name": "Jon"},{"name": "Doe"}],
"cities": [{"city": "Barcelona"},{"city": "Saragoza"}]
}
];
html:
<div *ngFor="let doc of documents; let last = last"> <!-- iterate over all documents, let last = last is optional -->
<p>Id: {{doc.id}}</p>
<!-- iterate over all names (n) for every document (doc) -->
<p>Names: <span *ngFor="let n of doc.names; last as lastName">{{n.name}}{{lastName ? '': ','}} </span></p>
<!-- iterate over all cities (c) for every document (doc) -->
<p>Cities: <span *ngFor="let c of doc.cities; last as lastCity">{{c.city}}{{lastCity ? '': ','}} </span></p>
<!-- optional , this will add a separator between documents-->
<hr *ngIf="!last"/>
</div>
Output:
I am writing code on Angular 2 including multiple dependent two-way binding models and need to bind those model in cascade form. On more specific, I have written data and code of a food selection with multiple dependent radio buttons.
JSON data:
{
"DishId": "TestingDish",
"ivDishTypes": [
{
"TypeId": "Chicken",
"ivProductSizes": [
{
"SizeId": "Half",
"Rate": 70
},
{
"SizeId": "Normal",
"Rate": 130
}
]
},
{
"TypeId": "Fish",
"ivProductSizes": [
{
"SizeId": "Half",
"Rate": 60
},
{
"SizeId": "Normal",
"Rate": 110
}
]
}
]
}
HTML code:
<mat-radio-group class="example-radio-group" [(ngModel)]="selectedItemType">
<strong>Select Dish Type</strong>
<mat-radio-button class="example-radio-button" *ngFor="let productType of selectedDish.ivProductTypes;
let idx = index" [value]="productType" [checked]="idx === 0">
{{productType.TypeId}}
</mat-radio-button>
</mat-radio-group>
<mat-radio-group class="example-radio-group" [(ngModel)]="selectedItemSize">
<strong>Select Dish Size</strong>
<mat-radio-button class="example-radio-button" *ngFor="let productSize of selectedItemType.ivProductSizes;
let idx = index" [value]="productSize" [checked]="idx === 0">
{{productSize.SizeId}}
</mat-radio-button>
</mat-radio-group>
Component section:
constructor(#Inject(MAT_DIALOG_DATA) public data: any) {
this.selectedDish = data.item;
// These Item Type and Size is bounded with front end
this.selectedItemType = this.selectedDish.ivProductTypes[0];
this.selectedItemSize = this.selectedItemType.ivProductSizes[0];
}
By default radio button selection:
selectedItemType = Chicken object & selectedItemSize = Chicken.Half object
When I click Fish radio button:
selectedItemType = Fish object & selectedItemSize = Chicken.Half object
Here I am expecting selectedItemSize = Fish.Half object on component data section, but it shows Fish.Half selection on HTML only. Since I have used the first bound model property in second.
It's working only when I clicked both levels of the radio buttons.
I am trying to build a simple accordion in Ionic 2 by pulling data from a json file.
I can iterate through the category and subcategories items to list those, however once a subcategory is clicked, I am not able to fetch the data from the subcategory object and display it (subcategory title) on a detail page. I have looked at many different tutorials/forums but couldn't find how to do this anywhere.
I imagine it is not just an issue with the path but I might need to iterate through the subcategory objects further?
json
{
"results": [
{
"category": "Category 1",
"subCategory": [
{
"title": "subCategory 1.1",
"word": "hello"
},
{
"title": "subCategory 1.2",
"word": "hello"
}
]
},
{
"category": "Category 2",
"subCategory": [
{
"title": "subCategory 2.1",
"word": "hello"
},
{
"title": "subCategory 2.2",
"word": "hello"
}
]
}
]
}
home.html
<ion-header>
<ion-navbar color="primary">
<ion-title>Categories</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngFor="let item of (items | async)?.results">
{{ item.category }}
<div *ngFor="let subItem of item.subCategory">
<button (click)="openDetails(item)">{{ subItem.title }}</button>
</div>
</ion-item>
</ion-list>
</ion-content>
home.ts
export class HomePage {
items: any;
subcategories: any;
constructor(public navCtrl: NavController, public http: Http) {
this.items = this.http.get("assets/data/results-data.json").map(res => res.json());
}
openDetails(item) {
this.navCtrl.push('FilmDetailsPage', {item: item});
}
}
detail.html
<ion-header>
<ion-navbar color="primary">
<ion-title>{{ item.subCategory.title }}</ion-title> // NOT WORKING
</ion-navbar>
</ion-header>
You need to send the subItem i.e. each subcategory and not the item to openDetails() function.
<button (click)="openDetails(subItem)">{{ subItem.title }}</button><!-- here -->
In your details.html,
you can access as
<ion-title>{{ subItem.title }}</ion-title> <!-- make sure the parameter in ts file has name subItem. -->