p-dropdown is not displaying the labels correctly - javascript

I have trouble getting the dropdown component to work. The dropdown seems to detect the items it should display because it widens the itemlist according to the number of items in the array. However the spaces are all blank.
This is the same dropdown box as from the example at https://www.primefaces.org/primeng/#/dropdown (the first one with header 'simple')
However with me it doesn't display anything. I copy pasted the exact same code, the only difference are the imports. When i go to the github repository i can see that they import
import {SelectItem} from '../../../components/common/api';
and
import {DropdownModule} from '../../../components/dropdown/dropdown';
Where I use
import {SelectItem} from 'primeng/api';
and
import {DropdownModule} from 'primeng/dropdown';
When i try to use the imports from github then it says it can find dropdownmodule and selectitem at those locations.
Heres my code:
interface City {
name: string,
code: string
}
export class Test implements OnInit {
cities1: City[];
selectedCity: City;
constructor() {
this.cities1 = [
{label:'Select City', value:null},
{label:'New York', value:{id:1, name: 'New York', code: 'NY'}},
{label:'Rome', value:{id:2, name: 'Rome', code: 'RM'}},
{label:'London', value:{id:3, name: 'London', code: 'LDN'}},
{label:'Istanbul', value:{id:4, name: 'Istanbul', code: 'IST'}},
{label:'Paris', value:{id:5, name: 'Paris', code: 'PRS'}}
];
}
}
heres the html
<p-dropdown [options]="cities1" [(ngModel)]="selectedCity" placeholder="Select a City" optionLabel="name" [showClear]="true"></p-dropdown>
<p>Selected City: {{selectedCity ? selectedCity.name : 'none'}}</p>
Anyone know how i can fix this?
Thank you

remove optionLabel and code will work -
<p-dropdown [options]="cities1" [(ngModel)]="selectedCity" placeholder="Select a City" [showClear]="true"></p-dropdown>
OptionLabel : Name of the label field of an option when an arbitrary objects instead of SelectItems are used as options.

add optionLabel with the key name from the json array. The key you want to represent as label.
<p-dropdown optionLabel="label" [options]="cities1" [(ngModel)]="selectedCity" placeholder="Select a City" [showClear]="true"></p-dropdown>

Try this:
<p-dropdown
[options]="cities1"
[(ngModel)]="selectedCity"
placeholder="Select a City"
optionLabel="value.name"
[showClear]="true">
</p-dropdown>
Note this: optionLabel="value.name"

Related

How to receive value of 'n' input boxes?

How to receive the input values of variable number of input boxes?
I searched a long time in Google but I'm not able to do it.
ParentComponent.html:
<my-Input [interfaces]="interfaces"> {{ title }}</my-Input>
ParentComponent.ts:
interface single_input{
title: string,
get_value(event: string): void;
}
interfaces: single_input[] = [
{
title: "something",
get_value(event){ console.log(event)}
}
];
ChildComponent.html:
<div *ngFor="let i of interfaces">
<Input (keyup)="i.get_value($event.target.value)"> {{ title }}</Input>
</div>
To log this in the console works, but I just want to bind the input values to the given interface and give it back by eventemitter to the parent.
How to do this? Do I need a class for it?
I got it now.
But it looks like a workaround. is there a better solution than following code?
Code-Update:
ParentComponent.ts:
interface single_input{
title: string;
value: string;
}
interfaces: single_input[] = [
{
title: "something",
}
];
ChildComponent.html:
<div *ngFor="let i of interfaces">
<Input (keyup)="i.value = $event.target.value"> {{ title }}</Input>
</div>
It is far simpler than what you are trying to do. Angular have specific mechanism to achieve this goal, one of them being the decorators #Input and #Output. You are already using the #Input decorator to pass in the data to the child component, now you just need to use the #Output decorator to pass the data back to the parent. I recommend looking at the docs and this example to have a better understanding on how this works. Below is an example for your use case.
ChildComponent.html
<div *ngFor="let i of interfaces">
<input (keyup)="onKeyUp(i, $event.target.value)"> {{ title }}</input>
</div>
ChildComponent.ts
import { Component, EventEmitter } from '#angular/core';
#Component({ ... })
export class ChildComponent {
...
#Input() interfaces;
#Output() childValue: EventEmitter<any> = new EventEmitter<any>();
// ^ Use a proper datatype ^
onKeyUp(source, value) {
this.childValue.emit({
source: source,
value: value
});
}
...
}
ParentComponent.html
<my-input [interfaces]="interfaces" (childValue)="onChildValueChange($event)"> {{ title }}</my-input>
ParentComponent.ts
import { Component} from '#angular/core';
#Component({ ... })
export class ParentComponent {
...
onChildValueChange(event) {
// Do what you want with it
const interface = this.interfaces.find(interface =>
interface.title === event.source.title);
console.log('[ParentComponent] Value from child component:', event);
console.log('[ParentComponent] Changed interface:', interface);
console.log('[ParentComponent] Changed value:', event.value);
}
...
}
Extra tip: Just for completeness, an equally popular approach, would be using a service to contain the data, where the child changes the data on the service and the parent read from it.

Select option with ngModel

I have a project that has a select of several questions and I would like the first one to appear by default.
I have seen an example of how to achieve this using the index, of the type:
<select>
<option *ngFor="let answer of answers; let i = index" [value]="answer.id" [selected]="i == 2">
{{answer.name}}
</option>
</select>
and it works, but when I want to bind the select to a property of the component, it is no longer selected:
<select [(ngModel)]=searchterms.answerId>
<option *ngFor="let answer of answers; let i = index" [value]="answer.id" [selected]="i == 2">
{‌{answer.name}}
</option>
</select>
You can see an example here:
https://stackblitz.com/edit/angular-rv9vqi
As say in some answers the solution is to set a default value to the serachterm, but the problem I have, (I am not able to reproduce it in the playground) is that I receive those answers from a service that asks to a back, and when the component is built it still does not have them and it gives me an error .... how can I make it assign those searchterms the value once they exist in the service?
You can use Angulars two-way data binding to bind to the value attribute of the <select> element. In your example it would look like this:
<select [(value)]="searchterms.answerId">
<option *ngFor="let answer of answers" [value]="answer.id">{{answer.name}}</option>
</select>
Notice how binding to the value attribute cleans up the option element, by enabling you to remove the [selected]="i == 2" and let i = index
However, like the others have mentioned you will want to initialize the desired default value in your component code.
Here is the working StackBlitz Demo with your code
You need to set the searchterms.answerId with a proper default value. In your case
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular 6';
answers = [
{name: "Answer 1", id: '1'},
{name: "Answer 2", id: '2'},
{name: "Answer 3", id: '3'},
{name: "Answer 4", id: '4'},
];
searchterms = {
answerId: this.answers[1].id //Set the default value properly
};
}
stackblitz
Then you should bind searchterms in your component.
you can do it inside constructor as follows.
this.searchterms.answerId = this.answers[1].id;
Demo

Angular Inputs View Displays, Any way to Quickly Swap Test Input Data?

How do I create Mock data to plug in and test displays? Everytime, we want to view an HTML rendering, have to literally copy and paste data into Typescript file. Is there any toolset to conduct this?
Currently testing #Inputs, which are being displayed in HTML
In researching following options,
It is not an API, so cannot use InMemoryDbService from “angular-in-memory-web-api” https://www.techiediaries.com/angular-inmemory-web-api/
Also not database, so cannot apply json-server https://medium.com/letsboot/the-perfect-mock-backend-to-start-with-an-angular-application-3d751d16614f
What options exist to quickly swap Inputs? or do people have to copy and paste into each file, is this customary in Angular?
Typescript
export class CustomerView implements OnInit {
#Input() customer: Customer;
this.customer.name = "Joe";
this.customer.address = "123 Maple STreet";
this.customer.city = "Atlanta";
this.customer.state = "GA";
this.customer.zip= "30314";
this.customer.phone = "555-444-77777";
HTML
<div class = "row">
<div> {{customer.name}} </div>
<div> {{customer.address}} </div>
<div> {{customer.city}} </div>
<div> {{customer.state}} </div>
<div> {{customer.zip}} </div>
<div> {{customer.phone}} </div>
</div>
Display example plcture
You can create a json file or Object with the required fields.
customerDummy = {
name: "Joe",
address: "123 Maple STreet",
city: "Atlanta",
state: "GA",
zip: "30314",
phone: "555-444-77777",
}
Whenever you are you create a variable just assign the value. For eg
#Input() customer: Customer = customerDummy;

Formbuilder setvalue() is not working as expected when used on dropdown selects

Angular 2,4 formbuilder setvalue() is not working as expected when used on dropdown selects.
I have the following dropdown select that gets populated with Github organizations:
<select name="org" formControlName="organizations">
<option *ngFor="let org of organizations" [ngValue]="org">{{org.organization.login}}</option>
</select>
Here is the javascript code that sets the Github organization that should be selected.
this.pipelineForm = fb.group({
name:'',
organizations:'',
repos: '',
branches:'',
runtime:'',
versions:''
});
userService.getOrganizations().subscribe((org:github)=>{
let organizationName = org.data[0];
this.organizations = org.data;
this.projects.subscribe((p)=> {
p[1].project.subscribe((f)=>{
this.pipelineForm.get("organizations").setValue(f.organizations, {onlySelf: true});
//this.pipelineForm.patchValue(f);
});
});
});
I expect the corresponding dropdown option to be selected when I pass the value to the setValue(). Instead, I get a blank option. I also tried with patchValue(). No luck.
I struggled with the same problem and found Igor's answer. It was too vague so I dug around more. I finally figured it out, and Igor's answer is correct albeit lacking in detail. Hopefully this will help anyone else in the future trying to get setValue() on dropdowns and object models to work happily together.
Generally, the object model passed into setValue() should be the same as the objects you inject into your dropdown selector. E.g. if of type Organization, then the setValue should be also be of type Organization. It's not necessary, however, to share completely identical properties.
To get the setValue() or patchValue() to work with an object model (as opposed to some primitive type), use the [compareWith] function as Igor pointed out.
From node_modules/#angular/material/select/typings/select.d.ts:
compareWith is a function to compare the option values with the selected values.
The first argument is a value from an option. The second is a value
from the selection. A boolean should be returned.
In your html template,
<select [compareWith]="compareOrgs" name="org" formControlName="organizations">
<option *ngFor="let org of organizations" [ngValue]="org">{{org.organization.login}}</option>
</select>
And in your component.ts file, define the compareOrgs() function:
compareOrgs(c1: any, c2: any): boolean {
return c1 && c2 ? c1.orgId === c2.orgId : c1 === c2;
}
Don't forget to call the setValue() function, for e.g. in ngOnInit() or in the callback function if it's async and you're fetching data.
E.g. in the callback from OP's code above,
// "organization" is whatever object you're trying to patch on the dropdown
this.pipelineForm.get("organizations").setValue(organization)
So what all this does is, the compareOrgs function will compare the value of the selected value (which is the object you passed into setValue, now labelled as c2 in compareOrgs) with each of the option values (c1). Specifically, it compares the orgId properties of the selected and option values. This is how the FormControl knows which value to pre-select on the dropdown.
You can now access the object with [ngValue].
This is a good resource that helped me: https://codeburst.io/angular-material-select-module-the-comparewith-function-9dfdb4035373
A little example, we want to save a number. see [ngValue]="org.id" and this.myForm.controls['organization'].setValue(value);
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormControl, FormGroup } from '#angular/forms';
interface Iorganization {
id: number;
name: string;
}
#Component({
selector: 'app-select',
template: `
<form [formGroup]="myForm" novalidate>
<select name="org" formControlName="organization">
<option *ngFor="let org of organizations" [ngValue]="org.id">{{org.name}}</option>
</select>
</form>
<button (click)="setOrg(1)">Org 1</button>
<button (click)="setOrg(2)">Org 2</button>
{{myForm.value |json}}
`,
styleUrls: ['./select.component.css']
})
export class SelectComponent implements OnInit {
organizations: Iorganization[];
myForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.organizations = [
{ id: 1, name: "org 1" },
{ id: 2, name: "org 2" },
{ id: 3, name: "org 3" },
{ id: 4, name: "org 4" }
];
this.myForm = this.fb.group({
organization: 1
})
}
setOrg(value: number) {
this.myForm.controls['organization'].setValue(value);
}
}
if we want to save a object -see {{myForm.value |json}}- we need make a few changes. see that we put [ngValue]="org", but the setOrg() function use a object to make setValue. And not, it's not valid setValue({id:1,name:'org1'})
import { Component, OnInit } from '#angular/core';
....
template: `
<form [formGroup]="myForm" novalidate>
<select name="org" formControlName="organization">
<option *ngFor="let org of organizations" [ngValue]="org">{{org.name}}</option>
</select>
....`
export class SelectComponent implements OnInit {
...
ngOnInit() {
this.organizations = [
{ id: 1, name: "org 1" },
....
];
this.myForm = this.fb.group({
organization: null
})
}
setOrg(value: number) {
let organization=this.organizations.find(o=>o.id==value);
this.myForm.controls['organization'].setValue(organization);
}
Use the attribute compareWith on your select tag:
<select ... [compareWith]="compareByName">
Then implement a simple function in your component
compareByName(org1: Org, org2: Org): boolean {
return org1 && org2 ? org1.name === org2.name : org1 === org2;
}

Getting select option to show the initial selected option value using Angular

I am having a hard time trying to get the select input to show the initially selected option using Angular. I have tried many options but none have worked so far. Not sure why this is causing me such a headache. Any help would be great, thank you.
The select input shows nothing until I select an option. Would like to dynamically select what option I want selected when app loads.
You can view what I have setup so far with the link below:
https://stackblitz.com/edit/angular-wga92l?file=app%2Fhello.component.ts
Component:
#Component({
selector: 'master-input',
template: `
<form>
<div class="form-group">
<label for="Master-Products">Select Master Product</label>
<select name="pow.name" (ngModelChange)="change($event)" [ngModel]="selectedValue" class="form-control" id="Master-Products">
<option *ngFor="let pow of powers" [ngValue]="pow.id" [selected]="pow.id == 3">{{pow.name}}</option>
</select>
</div>
</form>
`,
styleUrls: ['./master-input.component.scss']
})
export class MasterInputComponent {
#Output() hasChanged: EventEmitter<number> = new EventEmitter();
powers: any[] = [{ id: 1, name: 'Bead Ruptor Elite' }, { id: 2, name: 'Bead Ruptor 12' }, { id: 3, name: 'Bead Ruptor 96' }];
selectedValue: string = 'Bead Ruptor 96';
change(value: number) {
this.hasChanged.emit(value);
}
}
just Add ngOnInit function
powers: any[] = [ 'power1', 'power2', 'power3' ];
ngOnInit(){
this.selectedValue ='power3';
}
change(value:string) {
this.hasChanged.emit(value)
}
It was tested in your fiddle.
Please see working image

Categories