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?
Related
I use reactive forms within my app. In a certain form I want to display a required (Validators.required) select like this:
<select class="form-control"
[id]="dformControl.key"
[formControlName]="dformControl.key"
[multiple]="dformControl.multiple">
<option *ngIf="!dformControl.value"
value="undefined">
Choose ...
</option>
<option *ngFor="let opt of dformControl.options"
[value]="opt.value"
[selected]="dformControl.value == opt.value">
{{opt.label}}
</option>
</select>
The problem is whether I use value="undefined" or value="" the form control still is set to valid because it got a value. Do not present the value attribute results in value="Choose ...".
Am I using select with reactive forms in a false way or how would I be able to make the option "Choose ..." being not valid??
Assigning initial value of select control to null will do the trick. Try below,
model_property = null
....
this.fb.group({
....
'control_key' : [this.model_property, Validators.required]
...
})
Check this Plunker!!, Look into app/reactive/hero-form-reactive.component.ts file.
I updated the Plunker to include below and it seems to be working,
<select id="power" class="form-control"
formControlName="power" required >
// see the value is set to empty,
<option value="">Choose...</option>
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
</select>
Hope this helps!!
What I do is add a blank option and when that is selected since there is no value it is not valid.
<select class="form-control"
[id]="dformControl.key"
[formControlName]="dformControl.key"
[multiple]="dformControl.multiple">
<option></option>
<option *ngFor="let opt of dformControl.options"
[value]="opt.value"
[selected]="dformControl.value == opt.value">
{{opt.label}}
</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;
}
I am trying to use the 'track by' expression to track my selections by value, in an array of objects but, I'm unable to get it to work.
JS
var app = angular.module('cwsystem', []).controller('RegistrationCtrl', ['$scope', function($scope){
$scope.roles = [
{value: '110', position: 'Security Chief'},
{value: '111', position: 'Security Officer'}
];
}]);
HTML
<select name="userStatus" ng-model="user.userStatus" ng-options=" role.value as role.position for role in roles track by role.position" class="form-control input-sm" required>
<option value="">--Select Status--</option>
</select>
I want the browser to render the results like this:
<select name="userStatus" ng-model="user.userStatus" ng-options=" role.value as role.position for role in roles track by role.position" class="form-control input-sm" required>
<option value="">--Select Status--</option>
<option value="110">Security Chief</option>
<option value="111">Security Officer</option>
</select>
Can I get some assistance please on this problem?
ng-options does not accept "role.value as role.position for role in roles track by role.position" expression.
<select name="userStatus" ng-model="user.userStatus" ng-options=" role.value as role.position for role in roles" class="form-control input-sm" required>
<option value="">--Select Status--</option>
</select>
if you use above expression in ng-option you will get selected value in ng-model variable
Im a bit of a jQuery novice.
I have 5 options in a drop down menu.
I want to add a class in a div depending on which option is selected.
This class will then change the layout of the content using CSS.
Here is an example if it helps!
Thanks
<form>
<select>
<option id="1">layout 1</option>
<option id="2">layout 2</option>
<option id="3" selected>layout 3</option>
<option id="4">layout 4</option>
<option id="5">layout 5</option>
</select>
<div class="3">styled content</div>
</form>
You can use the ".attr()" to set the class attribute of the div onchange.
You're best to change the option id to value first. then:
$("select").change(function() {
$("div").attr("class", $(this).val());
});
(EDIT) Change it to:
$("select#np_blog_layout").change(function() {
$("div#changebox").attr("class", $(this).val());
});
What 'rudeovski ze bear' said, but if you still want to set it to the div's class to the selected elements id, here it is.
$('select').change(function() {
$('div').attr('class', $(this).attr('id'));
});
First off, you don't have to use id to your options. Put the values in value attribute. Put ID to your div and select so you can select them using jQuery.
<form>
<select Id="selectElement">
<option value="1">layout 1</option>
<option value="2">layout 2</option>
<option value="3" selected>layout 3</option>
<option value="4">layout 4</option>
<option value="5">layout 5</option>
</select>
<div id="styledContent" class="3">styled content</div>
</form>
On JS
//Attach event handler to select element's onchange event
$('#SelectElement').bind("change",changeStyle);
//The event handler
function changeStyle()
{
//Set class to selected value
$('#styledContent').class($('#SelectElement').val());
}
What is the best, in Perl, way to get the selected values of a multiple select form field?
<select name="mult" multiple="multiple">
<option value="1">Opt. 1</option>
<option value="2">Opt. 2</option> <!-- selected -->
<option value="3">Opt. 3</option>
<option value="4">Opt. 4</option> <!-- selected -->
<option value="5">Opt. 5</option>
</select>
I get regular form fields like this: $param1 = param('param1');
If you are using the CGI Module (and I really hope you are) then you can access the multiple values by assigning the param hash to an array and CGI does the rest. So in your example:
my #mult = $q->param('mult');
will store the selected values (2, 4) in the #mult array.