Searchable select element in React - html

I'm trying to build searchable select element in React. What is really important to me is:
Avoide jQuery
Posibility to set one of options as default selected
I have list of options, which now looks like that:
<select
onChange={props.onChange}
id={props.id}
className={props.style || "form-control"}>
{!props.defaultOption ?
<option value="" selected>Select</option> :
<option value={props.defaultOptionValue} disabled selected>{props.defaultOption}</option>}
{props.options.map((item, i) => {
if (item.id === props.defaultOptionValue) return false;
return <option key={i} value={item.id}>{item.name}</option>
})}
</select>
Nothing really complicated. I pass onChange handler, id and styles. If i provide defaultOptionValue and defaultOption in props, then it means i need to check this one as selected.
Datalist works great for me, but it doesn't support safari and i want to display label inside my input, not a value, as value is id and label name of the object.
I have already checked react-select, but it's missing option to set default value.

Related

Setting default selected value in select dropdown Vue.Js

I have a problem getting the default selected value using select in VueJs. I have tried in two instances:
Passing id and v-model fields in the select as:
<select v-model="sort_brand" id="sort-brand" class="form-control">
<option value="all" selected="selected">All(Brands)</option>
<option v-for="brand in brands" :value="brand.id">{{ brand.name }}</option>
</select>
The selected default value is empty in this case.
Passing sort_brand without id to select:
<select id="brand-id" class="form-control">
<option value="all" selected="selected">All(Brands)</option>
<option v-for="brand in brands" :value="brand.id">
{{ brand.name }}
</option>
</select>
The default selected value is populated but then i don't have the form binding for VueJs. Anyone please assist with this:
Vue.js will manipulate the selected attribute based on the v-model of the select and the option value. Thus trying to set the selected attribute will not work.
For your "All" option, you could assign the null value like this:
<option :value="null">All(Brands)</option>
And then set your sort_brand variable to null. Then vue.js will match the null sort_brand to the option with the null value.
Note: I used null here because that's the way I usualy do it, but I could use any other value. You could use the 'all' string also.
Update sort_brand to all in created hook which will set the option will value 'all' as default:
created (){
this.sort_brand = 'all';
}
You can also initialize the model in data itself.
data (){
return {
sort_brand : 'all'
}
}
The answers above (e.g. #Lunfel) work if your selection values are simple (null, "All", etc). If your combo is bound to complex JSON objects, then it's very difficult to set the bound variable and let it auto-select.
I found it much easier to find the option I wanted, based on the display text, in the mounted function() using JQuery, and then set the 'selected' attribute. How you do this depends on your version of JQuery. In recent versions (not sure when it changed, I'm running 1.10.2), you can use something like:
$("#sort-brand option").filter(function () {
return $(this).prop("label") == 'All';
}).prop("selected", true);
Older versions of JQuery don't have the prop() function, but had a somewhat better selector for the find() function. Try:
$('#sort-brand').find('option[text="All"]').attr('selected', 'selected');
See How to select an option by its text? for more discussion on selecting dropdown options with jQuery.

Angular: How to set a default selection on a select input

What I'm using
angular
firebase
Currently, a standard HTML select component
What I'm trying to achieve
When a user is filling out some details in some inputs, I have a drop down containing a number of options
I want to have a default option selected (not a placeholder, an actual selection)
Question
As I'm looping through an array (ngFor), how do I apply a 'selected' attribute to one of the options? Let's say for example that the array contained 'album 1', 'album 2'and 'album 3'. By default, I want 'album 2' to be automatically selected.
<select #selectedAlbum>
<option *ngFor="let album of albumList" [value]="folder.folder_title">{{album.album.title}}</option>
</select>
You can bind your select element to an ngModel and then on the initialisation of your component set the ngModel to be your desired default value and the option will be selected for you by the two way binding provided by ngModel.
i.e.:
<select #selectedAlbum [(ngModel)]="mySelectedItem">
and in your component:
mySelectedItem: string;
ngOnInit() {
this.mySelectedItem = 'album 2';
}
You can add a selected attribute:
example using a predefined item
<select #selectedAlbum>
<option *ngFor="let album of albumList" [value]="folder.folder_title" [selected]="ablum.ablum.title === 'album 2'">{{album.album.title}}</option>
</select>
example using an index
<select #selectedAlbum>
<option *ngFor="let album of albumList; let i = index;" [value]="folder.folder_title" [selected]="i === 1">{{album.album.title}}</option>
</select>
Note:
This method does not use two-way binding. This is a one-way binding as you currently have implemented. If you'd prefer to use two-way binding (which is much more elegant in general) I'd highly recommend digging deeper into form models.

Add an attribute on a condition with angular 2

I have a simple dropdown that is populated from an array.
Users will be editing a record in a form where the priority of the record can be selected from the mentioned dropdown. I'm having difficulty with setting the selected item in that dropdown.
Here's my code for that dropdown:
<select *ngIf="formModel" [(ngModel)]="record.priority" formControlName="priority">
<option value="-1">Select priority</option>
<option *ngFor="let priority of formModel.priorities"
[ngValue]="priority"
[innerHtml]="priority.name"
[selected]="priority.id == record.priority.id"></option>
</select>
The selected priority of the record is however not selected, the resulting HTML shows selected="true".
When I change the code to the following:
[selected]="(priority.id == record.priority.id ? '' : null)"
The result is selected="", but the option is stil NOT selected.
I have already confirmed that that particular option should be selected.
Also when I change the HTML in Firebug to just selected the option is selected.
So my question is: how can I add an attribute on a certain condition so that the attribute is not added to other elements with an empty value?
Using two-way-binding is discouraged in reactive forms. The point is to utilize the form controls instead. Why use reactive form, if you are using two-way-binding? That would mean the model driven form is totally redundant. So if you want to solve this problem using the model-driven form, I'd suggest the following:
Since you are using a separate object (record.priority) it cannot automatically be bound as the pre-selected value, you'd have to somehow create a reference. So when building a form you can do this:
this.myForm = this.fb.group({
priority: [this.formModel.priorities.find(x => x.id == this.record.priority.id)]
});
And the template would look like this:
<form [formGroup]="myForm">
<select *ngIf="formModel" formControlName="priority">
<option value="-1">Select priority</option>
<option *ngFor="let priority of formModel.priorities"
[ngValue]="priority"
[innerHtml]="priority.name"></option>
</select>
</form>
Now the value object you are getting from the form holds this value.
if having the record coming async, you can set a boolean flag to not show the form until the values have been set. Or you can build an empty form initially and then use setValue() for the form control.
DEMO
EDIT: Looking closer, that you want to have the condition to set null if there is no value for record.priority? That can be done well in the form control as well:
priority: [this.record.priority ? this.formModel.priorities.find(x => x.id == this.record.priority.id) : null]
Try this :
<select *ngIf="formModel" [(ngModel)]="record.priority.id" formControlName="priority">
<option value="-1">Select priority</option>
<option *ngFor="let priority of formModel.priorities"
[ngValue]="priority.id"
[innerHtml]="priority.name"></option>
</select>
[ngValue]="priority.id" and [(ngModel)]="record.priority.id" should point to the same value , and it will work automatically ,
There is no need to write [selected]="priority.id == record.priority.id"

Setting selected option of select control in an Angular 2 model-driven form

I have researched many similar existing answers on SO and elsewhere, but just can't find the solution to this.
I'm using the model-driven approach in Angular 2 to build my form, which is both an add and edit form. When in edit mode, the values are populated with data retrieved from a service: this aspect is all fine because the simple text inputs all bind correctly.
One of the properties is 'Country' and this is an object as follows:
export class Country {id: number; name: string;}
I want to bind this to a select control which will have the list of countries available, and the one from the model populated when the form loads. I want the value of the binding to be the country object, not just the id.
Here's the html of the select control:
<select class="form-control" id="country" formControlName="country">
<option value="default">--Select a country--</option>
<option *ngFor="let c of countries" [value]="c">{{c.name}} </option>
</select>
And here is where i try to to populate the value from the component class:
(<FormControl>this.personForm.controls['country'])
.setValue(this.person.country, { onlySelf: true });
But there is no selected option when the page loads, even though the console confirms that this.person.country exists and is populated with the correct object.
I can get it working with ids: changing to [value]="c.id" in the view and appending .id in the class, and then it works in that the right option is selected. The problem is that the select no longer emits an object for the country property, just the id. I tried changing [value] to [ngValue] and get the same result. I even added [ngModel]="country" to the select element and that didn't help either.
I'd be grateful for any help.
The issue is most likely that this.person.country is not the same country as in your countries array.
If we want to make them the same we can either explicitly subscribe to the valueChanges of the select control or bind [(ngModel)] to person.country:
subscribe to changes
code
this.countryForm.controls['country'].valueChanges.subscribe(country =>
this.person.country = country;
);
// initialize by finding the correct country object (this will overwrite the person's country object)
this.countryForm.controls['country'].setValue(countries.filter(c => c.id === person.country.id));
template
ngModel bind
We still have to make the objects match (compare strategy that Angular 2 uses which is really what JS uses)
code
this.person.country = this.countries.filter(c => c.id === this.person.country.id)[0];
template
<select class="form-control" id="country" formControlName="country" [(ngModel)]="person.country">
<option value="default">--Select a country--</option>
<option *ngFor="let c of countries" [ngValue]="c">{{c.name}}</option>
</select>
ngModel Plunker: http://plnkr.co/edit/UIS2V5rKh77n4JsjZtii?p=preview
subscription Plunker: http://plnkr.co/edit/yyZ6ol1NPD77nyuzwS2t?p=info

how to reset select in angular2

I have tow select lists (select1 and select2) in my form, select2 depends on select2 selection, when select1 selection change options in select2 must be change this work fine but my problem is that on change don't return to default option, it gives me last index of last select2 selection,
i want on change the select2 option change and index of selected option return to 0 or default option
I am using ng-model to deal with select in angular2
this my html code:
<td *ngIf="classificationCheck"><select name="classification_type" [(ngModel)]="message.classification_type"
class="form-control" [disabled]="isReply||isForward">
<option value="" disabled default>تصنيف موضوعي</option>
<option *ngFor= "let subType of classificationTypes">{{subType}}</option>
</select></td>
and this onChange function for select1 witch update select2 options:
classificationChange( event ){
if("غير محدد"==event){
this.classificationCheck=false;
this.message.classification_type=null;
}
else{
for(let classtype of this.classifications){
if(classtype.gen==event){
if(classtype.name)
{
this.classificationTypes=[];
this.classificationCheck=true;
for(let subType of classtype.name){
this.classificationTypes.push(subType);
}
}
}
}
}
}
Put an *ngIf on your select. Set it to true. When you want to reset, set it to false then back to true very quickly.
This was the official approach in RC4 until a proper approach was made available.
If a new approach is now available in the final release of ng2, I don't know.