I am trying to get some information by a select but I get a String and not the whole Object
My code is the following:
<!-- Select Scenario -->
<div class="form-group bottom">
<label class="col-md-4 control-label">{{ 'Scenario' | translate }}</label>
<div class="col-md-8">
<select class="form-control" #scenario (change)="getScenario(scenario.value);">
<option type="text" *ngFor="let scenario of scenarios" >{{scenario.Name}}</option>
</select>
</div>
</div>
but I get as a value the sceanrio.Name as a String.
I have tried to change the code for:
<option type="text" *ngFor="let scenario of scenarios" value="{{scenario}}">{{scenario.Name}}</option>
and
<option type="text" *ngFor="let scenario of scenarios" [ngValue]="scenario">{{scenario.Name}}</option>
with the aim of getting the object scenario as a value, but it does not work (i get [object Object]).
My scenario looks like:
export class Scenario {
Name: String;
Rec: [{
recName: String;
}];
IntConf: [{
DName: String;
}];
}
just Name is filled at that moment, but I would like to get the whole object (i guess with null in the paraments)
Any idea?
{{scenario.Name}} is mostly likely has an embedded object. Use a "|json" pipe to confirm like this {{ scenario.Name | json }}
To get an actual object binding you should use [ngvalue] instead of the plane HTML5 value.
Your result should look like this:
<option type="text" *ngFor="let scenario of scenarios" [ngvalue]="scenario">
{{scenario.Name}}
</option>
Related
In my Angular component I'm using 2 html select dropdowns. The model dropdown shows the models of the selected brand above. Currently the problem is that I want to store both as string but in code I get the whole object from brand dropdown. If I change ngValue of brand into [ngValue]="brand.name", the bind with the model select will not work anymore. Currently the selected car brand is on submit of my form stored as the brand object and the car model stored as a string.
How can I select a model of the selected brand and also store the brand as string?
This is my code
<form *ngIf="car" #carEditForm="ngForm" name="form" (ngSubmit)="carEditForm.form.valid
&& onSubmit()">
<label for="brand">Car brand</label>
<select class="form-control" [(ngModel)]="car.brand" name="brand" required>
<option *ngFor="let brand of brands" [ngValue]="brand">{{ brand.name }}</option>
</select>
<label for="model">Model</label>
<select *ngIf="car.brand" [(ngModel)]="car.model" class="form-control" name="model"
required>
<option *ngFor="let model of car.brand.models" value="{{ model }}">
{{ model }}
</option>
</select>
...
</form>
And the classes:
export class Car {
key: string
brand: string
model: string
}
export class Brand {
key: string
name: string
models: []
}
Edit: Solution in comments
I think I am having an issue with value binding. I have 2 dropdowns on my page currently. The rest of the page is using PrimeNg for UI and would like to make these dropdowns look the same as the rest of the page. How should I go about making this work.
One dropdown is a supervisor list.
<div class="ui-g form-group">
<label for="supervisors">Supervisors * </label>
<select
class="form-control"
id="supervisors"
required
[(ngModel)]="model.supervisor"
name="supervisor"
>
<option *ngFor="let sup of supervisors" [value]="sup">
{{sup}}
</option>
<div
[hidden]="supervisors.valid || supervisors.pristine"
class="alert alert-danger"
>
Supervisor is required
</div>
</select>
</div>
The other is a leave code list
<div class="ui-g-12 ui-md-1" id="test">
<label for="codes">Leave Codes * </label>
<select
class="form-control"
id="codes"
placeholder="Select Leave Code *"
required
[(ngModel)]="model.code"
name="code"
>
<option *ngFor="let cod of codes" [value]="cod">{{cod}}</option>
</select>
</div>
I have 2 arrays of values being called from my .ts file
supervisors = ['Alex',"Jones",'Joe','Rogan'];
codes = ['Personal Leave','Vacation Leave', 'Sick Leave'];
When I use the tags I just get an empty drop down. I tried just using initially but then I was not able to get the required fields to validate.
Did you import DropdownModule?
import {DropdownModule} from 'primeng/dropdown';
See the documentation, html binding should be
<p-dropdown [options]="supervisorList" [(ngModel)]="supervisor"></p-dropdown>
where supervisorList will be defined as SelectItem in controller and needs to be in a label + value format.
supervisorList: SelectItem[];
this.supervisorList= [
{label: 'Alex', value: 'Alex'},
...
];
In my dropdown for now all of the products are displayed, and I have like 200 products there, and dropdown is pretty large, I would like to display only 5-10 product for example, so it might look like this:
So basically all of the products would be there available for search, BUT ONLY 5 - 10 of them would be displayed, so dropdown would look more cleaner..
This is pure html of dropdown:
<div class="col-sm-6">
<select class="form-control dash-form-control select2" style="width: 100%;">
<option selected disabled>Search...</option>
<option>258-656 - Product 1 0,5l</option>
<option>358-656 - Product 2 0,75l</option>
<option>428-656 - Product 3 1kg</option>
</select>
</div>
And this is Angular modified:
<div class="col-sm-6">
<select class="form-control dash-form-control select2" style="width: 100%;">
<option selected disabled>Search...</option>
<option *ngFor="let p of products;" [value]="p.id">{{product.title}}</option>
</select>
</div>
And this angular way of course display all the values that are contained in products array.. and that's not it:)
Any kind of help would be awesome
Thanks guys
Cheers
In your component, import FormControl from #angular/forms and create an observable that takes a Product[].
public productCtrl: FormControl = new FormControl();
public products$: Observable<Product[]>;
now introduce a cold-observable that listens to input on the form-control, but until then, display the first 5 items.
this.products$ = this.productCtrl.valueChanges.pipe(
debounceTime(500),
startWith(null)
map(this.filterOrFirstFiveElements)
// implement a function
// that filters and returns your current product array or returns first five elements
// when a filter is provided and you get more that five elements, you can still only return first five elements of that result
);
Now in your template go ahead and adjust it to use the observable and mark the control as form-control.
<div class="col-sm-6">
<select class="form-control dash-form-control select2" style="width: 100%;">
<option selected disabled>Search...</option>
<option *ngFor="let p of products$ | async;" [value]="p.id">{{product.title}}</option>
</select>
</div>
<input type="text" [formControl]="productsCtrl" />
You need to import reactive-forms module into your module in order to be able to use [FormControl] directive.
Not directly related: As a user I would be completely confused when I see only five elements, use the filter and get a completely different result. An autocomplete is maybe a better solution. Show nothing, until user searches for a product.
Use Pipe
filter.pipe.ts
transform(value: any, args?: any): any {
console.log(args)
if(!value){
return null;
}
let arg=args ? args :5;
let limitTo=value.length >5 ? value.slice(0,arg) : value ;
return limitTo;
}
HTML
<div *ngFor="let d of data |filterpipe:5">
{{d.name}}
</div>
Example:https://stackblitz.com/edit/angular-r3kpxc
You could just use an index:
<div class="col-sm-6">
<select class="form-control dash-form-control select2" style="width: 100%;">
<option selected disabled>Search...</option>
<ng-container *ngFor="let p of products; let i = index;" >
<option *ngIf="i < 5" [value]="p.id">{{product.title}}</option>
</ng-container>
</select>
</div>
I have the following code:
<select class="form-control" required>
<option *ngFor="let car of cars" type="text">{{car.Name}}</option>
</select>
my problem is that i can get just a name, so *ngFor fails.
is there a way in HTML to make a condition like. If not Javascript or Jquery
//There are more than 1 option
if(options.length>1){<option *ngFor="let car of cars" type="text">{{car.Name}}</option>}
//There is only an option
else {<option *ngIf="car" type="text">{{car.Name}}</option>}
Car
export class Car {
id: String;
name: [{
brand: String,
}
}]
}
JSON returns an Array[] when there are more than one element. If not, it returns an Object{} so I can not use *ngFor
Solved
The problem was in the back-end, and not in the front-end
You can use *ngIf directive like:
<select id="oneICO" class="form-control" required *ngIf="cars.length > 1">
<option *ngFor="let car of cars">{{car.Name}}</option>
</select>
<input type="text" *ngIf="cars.length < 2">{{car.Name}}</input>
Checking if a variable is an array in the template is sort of nasty How to check type of variable in ngIf in Angular2
It would be better to check if !(cars instanceof Array) and then turn it into an array in your javascript code.
In html you can use ngif in angular2
<div *ngIf="options.length>1">
<option *ngFor="let car of cars" type="text">{{car.Name}}</option>
</div>
or simple put the next code in html
<option *ngIf="options.length == 1 " type="text">{{car.Name}}</option>
cars is not a collection so you don't need any angular directives:
<select id="oneICO" class="form-control" required>
<option>{{cars.Name}}</option>
</select>
In which case, rename cars to car so that it signifies a single item.
[It is a little pointless, though, have a select with only a single option.]
Note that an option does not have a type attribute.
Your original code is fine. There's nothing wrong with it.
<select id="oneICO" class="form-control" required>
<option *ngFor="let car of cars" type="text">{{car.Name}}</option>
</select>
If you have single car, make an array of single element and it will work just fine.
cars = ['Honda']
If you have multiple cars, you'll have something like this.
cars = ['Honda', 'Toyota', 'Mitsubishi']
I have a template driven form which has multiselect field called assets.
I am using semantic UI.
<div ngModelGroup="assets">
<div class="field">
<label for="resourceName">Assets</label>
<div class="form-control">
<select ngModel name="resourceName" multiple="" #resourceName="ngModel" id="multi-select" class="ui dropdown" required>
<option *ngFor = "let x of resources" value ="{{x.resourceName}}" >{{ x.resourceName }}</option>
</select>
</div>
</div>
</div>
the json I am getting from the dropdown is in the format:
"assets":{"resourceName":["laptop","keyboard"]}
but I want it in this format:
"assets":[{"resourceName":"laptop"},{"resourceName":"keyboard"}]
How do I do that?
You could use map transformation over array to get desired output.
this.resources = this.assets.resourceName.map(i => { resourceName: i})