NgFor only supports binding to Iterables such as Arrays while using array to create a dropdown selection - arrays

I am getting the below error while running the application:
ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'subLandscape'. NgFor only supports binding to Iterables such as Arrays.
The subLandscape variable I am referring to in the HTML is an array but it throws an error while using it with "ngFor"
HTML:
<div class="form-group" [class.has-error]="subLandscape.invalid && subLandscape.touched">
<strong>Sub Landscape</strong>
<br>
<p>Please choose from one of the Sub Landscape options. Sub Landscape options are for reporting only.</p>
<label class="control-label">SubLandscape:</label>
<mat-select #subLandscape="ngModel" type="text" class="form-control" name="subLandscape" [ngModel]="model.subLandscape">
<mat-option *ngFor="let item of subLandscape">
{{ item }}
</mat-option>
</mat-select>
<div *ngIf="subLandscape.invalid && subLandscape.touched" class="alert alert-danger">
Select the Sub Landscape from the provided list.
</div>
</div>
Model:
export class SModel {
constructor (
public description: string,
public reasons: string,
public projectName: string,
public subLandscape: string,
public centerdata: string,
public nom: number,
public size: string,
public dbgh: string
) {
}
}
Component:
import { Component, OnInit } from '#angular/core';
import { Standalone } from '../standalone';
import { StandaloneModel } from '../models/standalone.model';
import {MatTableModule, MatTableDataSource} from '#angular/material/table';
#Component({
selector: 'app-standalone-form',
templateUrl: './standalone-form.component.html',
styleUrls: ['./standalone-form.component.css']
})
export class StandaloneFormComponent {
public project: string[] = ['', 'appdev', 'apptest', 'appqa'];
public subLandscape: string[] = ['DEV', 'Testing', 'QA', 'UAT'];
public dataCenter: string[] = ['PDC', 'SDC'];
public model = new SModel('', '', '', '', '', 0, '', '');
}

Probably because it is unable to differentiate between subLandscape from
#subLandscape="ngModel" and the component property array public subLandscape: string[] = ['DEV', 'Testing', 'QA', 'UAT'];. Change the name of either should solve the problem

Related

I can't select options of mat-select and can't make the selected option appear in console

I have the following problem: I have a drop down list with 2 items. I need the first one to appear by default and that when selecting either of the two its value is shown in the console and saved in a variable. I have the following code:
HTML
<td>
<mat-select name="tipoCdp" (change)="onChangeCdp($event.value)" [(ngModel)]="tipoCdpValue">
<ng-container *ngFor="let gas of tipoc">
<mat-option [value]="gas.viewValue">
{{gas.viewValue}}
</mat-option>
</ng-container>
</mat-select>
</td>
TS
interface tipoCdp {
value: string;
viewValue: string;
}
#Component({
selector: '...',
templateUrl: '...',
styleUrls: ['...']
})
export class showValue implements OnInit {
constructor (...) { ... }
tipoc: tipoCdp[] = [
{value: 'gasto-0', viewValue: 'GASTO'},
{value: 'modificacion-1', viewValue: 'MODIFICACIÓN ANEXO DECRETO'}
];
//selected = this.tipoc[0].value; --> /* With this line I was selecting the firts element but the value was burned */
onChangeCdp(event) {
console.log(event);
this.tipoc = event;
}
}
When I run the program in "event" the selected item appears, but then the following error appears on the console:
"Error trying to diff 'GASTO'. Only arrays and iterables are allowed"
Thanks for your help!
In your template you are setting the value of the option from the gas.viewValue which will not match. If you replace it with gas.value and adjust your component class like this working example:
<mat-select name="tipoCdp" [(ngModel)]="tipoCdpValue">
<ng-container *ngFor="let gas of tipoc">
<mat-option [value]="gas.value">
{{gas.viewValue}}
</mat-option>
</ng-container>
</mat-select>
Your component class:
...
tipoCdpValue: any;
constructor() {
this.tipoCdpValue = this.tipoc[0].value; // to get the first option selected
}
...
If you want to listen on the selection changes you could add (ngModelChange)="onChange($event)" on your mat-select element

Write out what i select in my <select> list in angular

I want to write out the option i choose from my select list. I know that i should use change but now how i should use it. !now im just writing to get the letters in!
My ts file:
import { Component, OnInit } from '#angular/core';
import { selectBeverage } from "../interface-beverage";
#Component({
selector: 'app-select-beverage',
templateUrl: './select-beverage.component.html',
styleUrls: ['./select-beverage.component.css']
})
export class SelectBeverageComponent implements OnInit {
beverages: selectBeverage[] = [
{ id: 1, drink: "Beer" },
{ id: 2, drink: "Soda" },
{ id: 3, drink: "Wine" },
{ id: 4, drink: "Water" }
];
clickedBeverage(){
}
constructor() {
}
ngOnInit(): void {
}
}
My template file:
<select [(ngModel)]="beverages">
<option *ngFor="let b of beverages" [value]="b.id">
{{b.drink}}
</option>
</select>
<br><br>
One {{selectedOption}}, coming right up! ```
Create a variable in the typescript file named beverageToDisplay and bind to that in the template within the <select> tag.
.ts
beverageToDisplay: string;
.html
<select [(ngModel)]="beverageToDisplay">
<option *ngFor="let b of beverages" >
{{b.drink}}
</option>
</select>
<p *ngIf="beverageToDisplay">One {{beverageToDisplay}}, coming right up!</p>
Working stackblitz found here.
The [(ngModel)] of the select contains the selected value, not the list of options.
.ts file:
export class SelectBeverageComponent implements OnInit {
...
// add member here
selectedOption: any; // instead of any one could use something more precise in the next step
...
}
Template file:
<select [(ngModel)]="selectedOption"> <!-- i corrected value of ngModel, it contains the selected value -->
<option *ngFor="let b of beverages" [value]="b.id">
{{b.drink}}
</option>
</select>
<br><br>
One {{selectedOption | json}}, coming right up! ```

ERROR TypeError: Cannot read property 'serviceId' of undefined

Iam using nested json as input to Angular 6 where below is what my json structure looks like:
{"contractId":1,"contractName":"Temp","contractServiceList":[{"id":1,"serviceId":{"serviceId":1,"serviceName":"Emergency Room"},"providerTier":"Tier 1","coinsurance":100.0,"copay":10.0,"penaltyApplies":"Y","penaltyRule":"Non Emergency ER Use","penaltyType":"Dollar Amount","penaltyValue":300.0,"deductibleApplies":"Y"}]}
In component.ts, my code is:
export class AppComponent implements OnInit {
services: Service;
serviceId: ServiceId[];
contract: Contract[];
constructor(private formBuilder: FormBuilder, private router: Router, private contractService: ContractService) { }
addForm: FormGroup;
ngOnInit() {
this.serviceId = [
{serviceId: '1', serviceName: 'Emergency Room'},
{serviceId: '2', serviceName: 'OP Radiology'}
];
component.html :
<div class="form-group col-xs-6">
<label for="serviceName">Category Of Services:</label>
<select id ="serviceName" formControlName="serviceName" name="serviceName" class="form-control">
<option *ngFor="let serv of serviceId" [value]="serv.serviceId">{{serv.serviceName}}</option>
</select>
</div>
I am submitting all the values in the form as (ngSubmit)="onSubmit" and subscribing it as below:
onSubmit() {
this.contractService.saveContract(this.addForm.value)
.subscribe( data => {
alert('Contract created successfully');
});
}
Not sure why it's not able to take serviceId value. Any help is appreciable!!

PrimeNG multiselect not binding in Model Driven form when pulling "typed" data from server

I am using PrimeNG Multiselect in a reactive Angular form.
I can see the array of values coming back from the server through the chrome dev tool, but I cant figure out how to get it to bind to the multi select.
module is imported in the component and the app module:
import { MultiSelectModule } from 'primeng/multiselect';
template:
<p-multiSelect [options]="activities" [optionLabel]="ActivityName" [panelStyle]="{minWidth: '300px'}" [showHeader]="true" formControlName="selectedActivities"></p-multiSelect>
Class:
export class ChemicalEditComponent implements OnInit {
activities: ActivityType[];
selectedActivities: ActivityType[];
constructor(
private _chemicalService: ChemicalService,
private fb: FormBuilder
) {
this.getActivities();
this.getSelectedActivities();
this.createForm();
}
ngOnInit() {
this.getChemical();
}
getActivities(): void {
this._chemicalService.getActivities().subscribe(result => this.activities = result);
}
getSelectedActivities(): void {
this._chemicalService.getActivitiesByChemical(this.chemicalId).subscribe(result => this.selectedActivities = result);
}
createForm() {
this.chemicalForm = this.fb.group({
brandName: '',
commonName: '',
formulation: '',
selectedActivities: ''
});
}
rebuildForm() {
this.chemicalForm.reset({
brandName: this.chemical.BrandName,
commonName: this.chemical.CommonName,
formulation: this.chemical.Formulation,
selectedActivities: this.selectedActivities
});
}
The json returned from the server looks like this:
0:{ActivityTypeId: 61, ActivityName: "Driving"}
1:{ActivityTypeId: 62, ActivityName: "Strolling"}
I'm seeing all the examples use "label" and "value" but mine is typed from the server. I'm assuming the problem is I need to specify what is the label & value, so I added the [optionLabel] tag but that didnt help.

Angular dynamic array showing all results not just data under id

I am still trying to learn what seems to me like advanced Angular 5. The below code does enter the "id" number from the array into the url as expected, but when I go to model/1 it shows my all the objects from the array. I need to only see the object under id 1 and same for each object in the array. I have found so much conflicting information online, from mapping to queries that I'm not even sure where to being and everything I've tried has led to no better results. I have included all the code I'm working with.
I have an array of objects in my json file-
[
{
"id": 1,
"label": "Metal Man",
"sample": "/assets/img/metalman1.png",
"fab": "https://sketchfab.com/models/1b3cb7f8a77145bc8616075e9036b025/embed",
"img1": "/assets/img/metalman1.png",
"img2": "/assets/img/metalman2.png",
"img3": "/assets/img/metalman3.png"
},
{
"id": 2,
"label": "Magrot",
"sample": "/assets/img/magrot1.png",
"fab": "https://sketchfab.com/models/e20c8ade2f16452ca7f440aa84fc8e33/embed",
"img1": "/assets/img/magrot1.png",
"img2": "/assets/img/magrot2.png",
"img3": "/assets/img/magrot3.png"
},
{
"id": 3,
"label": "Baseball and Bat",
"sample": "/assets/img/ball1.png",
"fab": "https://sketchfab.com/models/781c60d3449b46f996a081ae36c20cce/embed",
"img1": "/assets/img/ball1.png",
"img2": "/assets/img/ball2.png",
"img3": "/assets/img/ball3.png"
}
]
My template for each of the above objects-
<div class="columnFlex mainBlock" *ngFor="let model of modelwork">
<div class="modelImagery">
<h1>{{ model.label }}</h1>
<iframe [src]='sanitizer.bypassSecurityTrustResourceUrl(model.fab)'
frameborder="1" allowvr allowfullscreen mozallowfullscreen="true"
webkitallowfullscreen="true" onmousewheel=""></iframe>
<img [src]="model.img1" />
<img [src]="model.img2" />
<img [src]="model.img3" />
</div></div>
And my Activatedroute set up-
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { CommonModule } from '#angular/common';
import { DomSanitizer } from '#angular/platform-browser';
import { ActivatedRoute } from '#angular/router';
import { Router } from '#angular/router';
#Component({
selector: 'app-model',
templateUrl: './model.component.html',
styleUrls: ['./model.component.css']
})
export class ModelComponent implements OnInit {
modelwork: any;
constructor( private route: ActivatedRoute, private router: Router, private http: HttpClient, public sanitizer: DomSanitizer ) {
this.sanitizer = sanitizer;
this.route.params.subscribe(params => {this.modelwork = params['id'];});
}
ngOnInit(): void {
this.http.get<any>('./assets/models.json').subscribe(
data => {
this.modelwork = data;
})
}
}
Any clarification on what I'm needing to do would be so appreciated! I'm trying to learn Angular in days and it is more complicated than I had expected. Thank you for taking the time to look at this!
I don't see anything advanced here. You simple have two asynchronous operations that both set the variable 'modelwork'. One of the operations sets modelwork to an integer and the other sets it to a json array. depending on which operation resolves first.
Edit
Looking at your comment, i see what you want to do. Here's an example:
chosenIndex: any;
modelwork: any;
constructor( private route: ActivatedRoute, private router: Router, private http: HttpClient, public sanitizer: DomSanitizer ) {
this.sanitizer = sanitizer;
}
ngOnInit(): void {
this.route.params.subscribe(params => {
this.chosenIndex = params['id'];
this.http.get<any>('./assets/models.json').subscribe(data => {
this.modelwork = data.filter(d => d['id'] == this.chosenIndex);
})
});
}
Modelwork will now contain an array of 1 object. The one object you want. You can alter this example to get whatever output you want.

Resources