Get text from selected option - select

I have a form with some <select> bound to an object comming from a webservice :
<select [(ngModel)]="configDatas.type" name="type" id="type">
<option value="0">Disabled</option>
<option value="1">Day</option>
<option value="2">Week</option>
</select>
<select [(ngModel)]="configDatas.days" name="days" id="days">
<option value="0">Monday</option>
<option value="1">Tuesday</option>
<option value="2">Wednesday</option>
</select>
Everything work as expected on this side.
I need to add at the end of my form a sentence which is a summary of the users's choice.
Something like :
<span> You selected type {{configDatas.type}} with day {{configDatas.days}}</span>
but instead of the value i'm looking for the text of the option.
I would like to see something like :
You selected type Week with day Monday
Is this possible directly in the template without using any kind of conversion on the component side ?

This may be a version difference, but the accepted answer didn't work for me. But pretty close did. this is what did the trick for me.
(change)="updateType(type.options[type.options.selectedIndex].text)

Updated: You can use the change event to keep track of the newly selected option:
<select [(ngModel)]="configDatas.type" name="type" id="type" #type (change)="updateType(type.options[type.value].text)">
<option value="0">Disabled</option>
<option value="1">Day</option>
<option value="2">Week</option>
</select>
<select [(ngModel)]="configDatas.days" name="days" id="days" #days (change)="updateDay(days.options[days.value].text)">
<option value="0">Monday</option>
<option value="1">Tuesday</option>
<option value="2">Wednesday</option>
</select>
<span> You selected type {{selectedType}} with day {{selectedDay}}</span>
export class App {
configDatas: any;
selectedType: string;
selectedDay: string;
constructor() {
this.configDatas = {
'type': '',
'days': ''
};
}
updateType(text: string) {
this.selectedType = text;
}
updateDay(text: string) {
this.selectedDay = text;
}
}
Updated Example http://plnkr.co/edit/ay7lgZh0SyebD6WzAerf

Another way to accomplish this is to use complex objects for your select list options.
You declare an interface for your options:
export interface Day {
id: number;
text: string;
}
Give it some options in the constructor:
this.days = [
{id: 0, text: 'Monday'},
{id: 0, text: 'Tuesday'},
{id: 0, text: 'Wednesday'}
];
Bind it to the option list. It's important to use ngValue here:
<select [(ngModel)]="configDatas.days" name="days" id="days">
<option *ngFor="let day of days" [ngValue]="day">{{day.text}}</option>
</select>
And finally output it:
<span> You selected type {{selectedType}} with day Id: {{configDatas.days.id}}, Text: {{configDatas.days.text}}</span>
Full example: http://plnkr.co/edit/kDanyC

Is this possible without keeping a separate array for each select ?
Not sure of the aversion to using two arrays to solve this but two functions could fix it.
<span> You selected type {{displayType(configDatas.type)}} with day {{displayDate(configDatas.days)}}</span>
Then just have some functions that return the text you want.
displayType(type) : string {
if (type == 0) {
return "disabled"
} else { //continue adding ifs
return ""
}
}
A objectively nicer way would to have two arrays that contain both the id and the text to display and then use a *ngFor to build the options up.

In simple way to get selected option text using (change)="selectDay($event)" event
<select [(ngModel)]="configDatas.days" name="days" id="days" (change)="selectDay($event)">
<option value="0">Monday</option>
<option value="1">Tuesday</option>
<option value="2">Wednesday</option>
</select>
In TS File
selectCity(event:any) {
console.log(event.target[event.target.selectedIndex].text);
let day = event.target[event.target.selectedIndex].text;
}

Related

validation on if condition in Laravel

How to give a validation on if condition like in my project case there are two inputs one is deal type and one is event name .so i have to give a condition like if deal type is single then i have to validate that event name otherwise no.
Here is my view :
<select name="deal_type">
<option value="">--Select--</option>
<option value="annual">Annual</option>
<option value="single">Single</option>
</select>
<select name="eventname">
<option value="">--Select--</option>
<option value="event1">Event1</option>
<option value="event2">event2</option>
</select>
my validation request.php :
public function rules()
{
return [
'deal_type'=>'required',
'eventname'=>'required_if:deal_type,single'
];
}
I was trying something like above but it is not working .Any suggestions please.

Angular cast select value to int

I have a form with different selects like :
<select [(ngModel)]="selected.isConnected" (ngModelChange)="formChanged()" name="etat" id="etat" class="form-control">
<option value="0">Not connected</option>
<option value="1">Connected</option>
</select>
My backend expect to receive an int in the "isConnected" attribute. Unfortunately as soon as I change the value of the select the attribute is cast to a string :
{
isConnected : "0", // 0 expected
}
For standard <input> I could use type="number" but for a <select> I'm clueless.
Is there a way to force angular 2 to cast the data to int ?
Use [ngValue] instead of "value":
<select [(ngModel)]="selected.isConnected" id="etat">
<option [ngValue]="0">Not connected</option>
<option [ngValue]="1">Connected</option>
</select>
If you want cast it within formChanged() method (Which you haven't provided yet).
You should use + symbol as shown below,
formChanged(): void {
selected.isConnected = +selected.isConnected;
...
}
No, sadly you're forced to parse it on your own in the formChanged() method, since you always get a string back from the select.
You could try it with something like this:
formChanged(): void {
selected.isConnected = parseInt(selected.isConnected);
// ...
}
You can send a Number variable to select and assign the value for that select element. Then if you want to capture the value when it changes, you can add (change) event to select and retrieve the value as shown below.
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `<select value="{{isConnected}}" (change)="printConnected($event.target.value)" name="etat" id="etat" class="form-control">
<option value="0">Not connected</option>
<option value="1">Connected</option>
</select>
<div *ngIf="changed">You've selected {{isConnected}}<div>`
})
export class AppComponent {
isConnected : number = 1;
changed : boolean = false;
printConnected(value){
this.isConnected = value;
this.changed=true;
}
}
You can view an example at http://plnkr.co/edit/xO2mrTdpTGufkgXqdhYD?p=preview
I am using reactive bindings and do not want to use [(ngModel)]. Instead I created a piped observable that uses JSON.parse(value) (because +value doesn't handle "null"):
*.component.html:
<div class="col-lg-4 form-group">
<label>Group Type</label>
<select class="form-control" (change)="groupType$.next($event.target.value)">
<option [value]="null"></option>
<option *ngFor="let groupType of filterData.groupTypes" [value]="groupType.id">{{groupType.label}}</option>
</select>
</div>
<div class="col-lg-4 form-group" *ngIf="filteredGroups$ | async as groupOptions">
<label>Group</label>
<select class="form-control" (change)="group$.next($event.target.value)">
<option [value]="null"></option>
<option *ngFor="let group of groupOptions" [value]="group.id">{{group.label}}</option>
</select>
</div>
<div class="col-lg-4 form-group">
<label>Status</label>
<select class="form-control" (change)="status$.next($event.target.value)">
<option [value]="null"></option>
<option *ngFor="let status of filterData.statuses" [value]="status.id">{{status.label}}</option>
</select>
</div>
*.component.ts:
group$ = new BehaviorSubject<string>(null);
groupId$ = this.group$.pipe(
map((groupId: string) => JSON.parse(groupId) as number)
);
groupType$ = new BehaviorSubject<string>(null);
groupTypeId$ = this.groupType$.pipe(
map((typeId: string) => JSON.parse(typeId) as number)
);
status$ = new BehaviorSubject<string>(null);
statusId$ = this.status$.pipe(
map((statusId: string) => JSON.parse(statusId) as number)
);
[ngValue] is intended for objects. It generates an artificial option value even for numeric constants. For those who might be concerned about tests or readability, you can expand two way binding microsyntax
<select [ngModel]="selected.isConnected"
(ngModelChange)="selected.isConnected=$event && +$event" id="etat">
<option value="0">Not connected</option>
<option value="1">Connected</option>
</select>

Value of <select><option> coming back as string

Is there any way to have the value of an <option> to be set to an actual integer? I have the following html code:
<select id="proteinperc" onchange="setMacrosProtein()">
<option value="0" selected>0%</option>
<option value="5">5%</option>
<option value="10">10%</option>
<option value="15">15%</option>
<option value="20">20%</option>
<option value="25">25%</option>
<option value="30">30%</option>
<option value="35">35%</option>
<option value="40">40%(Rec.)</option>
<option value="45">45%</option>
<option value="50">50%</option>
<option value="55">55%</option>
<option value="60">60%</option>
<option value="65">65%</option>
<option value="70">70%</option>
<option value="75">75%</option>
<option value="80">80%</option>
<option value="85">85%</option>
<option value="90">90%</option>
<option value="95">95%</option>
<option value="100">100%</option>
</select>
Then I have the script below that is trying to access these option values and perform calculations using them. The problem is that when I do any calculations with them, all I get is string concatenation or strange values.
function setMacrosProtein() {
myProtein = document.getElementById("proteinperc").value;
var removeValue = 101 - (myProtein + myFats + myCarbs);
alert(removeValue); // Alert here just for testing the first calculation.
var x = document.getElementById("fatperc").options.length;
for (i = 0; i < x; i++) {
// Check fatperc
if (document.getElementById("fatperc").options[i].value + myFats >= removeValue) {
document.getElementById("fatperc").options[i].disabled = true;
} else if (document.getElementById("fatperc").options[i].value + myFats < removeValue) {
document.getElementById("fatperc").options[i].disabled = false;
}
// Check carbperc
if (document.getElementById("carbperc").options[i].value + myCarbs >= removeValue) {
document.getElementById("carbperc").options[i].disabled = true;
} else if (document.getElementById("carbperc").options[i].value + myCarbs < removeValue) {
document.getElementById("carbperc").options[i].disabled = false;
}
}
//setCals();
}
If there is no way to return an integer from an option value, I do have a workaround in mind but with a small issue. I could set up a new array with mirroring values to the options list, ie: array[0] would be equal to option[0] and I could check against the array in my if statements.
However, how would I set a variable to the currently selected option this way? How do I reference the current selected option's position in the option array to get the mirrored position in my newly created array? To clarify, if the selected option is currently option[4], how do I reference its position to then pull array[4]'s value?
You could use parseInt() to get the int value from it like this:
myProtein = parseInt(document.getElementById("proteinperc").value);
In javascript file try to use parseInt(...).
Use the unary operator +. Easier than parseInt(). Simply put a plus in front of what you'd like to convert to a number.
Example:
<select id="movie">
<option value="10">Casablanca ($10)</option>
<option value="12">Rear Window ($12)</option>
<option value="8">Vertigo ($8)</option>
<option value="9">Rosemary's Baby ($9)</option>
</select>
const movieSelect = document.getElementById('movie');
const ticketPrice = +movieSelect.value;

Rails: Nested dropdown of categories

I am using the ancestry gem to allow Categories to nest, and I want to be able to create a dropdown showing the nesting when a user selects a category for a new product.
I can create the nested list, but it uses the parent categories as labels for option groups instead of as selectable elements.
First attempt
<%= select_tag "product[category_id]",
option_groups_from_collection_for_select(#store.categories, :children, :name, :id, :name, #product.category.id),
{ include_blank: true } %>
Which generates something like this:
<select id="product_category_id" name="product[category_id]">
<option value=""></option>
<optgroup label="Root Category 1"></optgroup>
<optgroup label="Root Category 2">
<option value="3">Child Category 1</option>
</optgroup>
</select>
When what I really want is just:
<select id="product_category_id" name="product[category_id]">
<option value=""></option>
<option value="1">Root Category 1</option>
<option value="2">Root Category 2</option>
<optgroup>
<option value="3">Child Category 1</option>
</optgroup>
</select>
Other attempts
I also tried generating the list with content tags:
def grouped_options(categories, selected_id = nil)
body = ''
categories.map do |category|
body << content_tag(:option, category.name, { value: category.id, selected: category.id == selected_id })
if category.children.present?
body << content_tag(:optgroup) do
grouped_options(category.children)
end
end
end
body.html_safe
end
However, this approach left gaps in the list where the optgroup label should be, and you can't really go more than 1 level deep.
So...
Is there a way I can nicely nest everything in a select and be able to select each level, or should I start considering a javascript/unordered list implementation instead?

How to get value of selected text by tag name, not id

I only have names of tags, no ids. Need to figure out a way to get text of selected dropdowns. This is the HTML:
<SELECT name="selectRightName">
<OPTION value="76" >1</OPTION>
<OPTION value="200" >2</OPTION>
<OPTION value="201" >3</OPTION>
<OPTION value="202" >4</OPTION>
<OPTION value="203" >5</OPTION>
</SELECT>
By some reason this returns empty value:
$(document).ready(function(){
alert(productName);
alert(selectRightName);
$('select[name=selectRightName]').change(onSelectChange);
$('select[name=selectLeftName]').change(onSelectChange);
});
function onSelectChange(){
var fselected = $('select[name=selectRightName] option:selected');
var sselected = $('select[name=selectLeftName] option:selected');
alert(fselected + " " + sselected);
The attribute in your HTML starts with a capital S, but your selector isn't reflecting it, and attribute selectors are case-sensitive everywhere.
var fselected = $('select[name=SelectRightName] option:selected');
Also there's a stray ) in your HTML, not sure what that's doing there but you should remove it.