Playframework scala helper for select input with optgroup - scala

Is in playframework scala helper to achive optgroup in input select?
Example:
http://jsfiddle.net/g4ffzvs8/
Code:
<select style="width:300px" id="source">
<optgroup label="Alaskan/Hawaiian Time Zone">
<option value="AK">Alaska</option>
<option value="HI">Hawaii</option>
</optgroup>
<optgroup label="Pacific Time Zone">
<option value="CA">California</option>
<option value="NV">Nevada</option>
<option value="OR">Oregon</option>
<option value="WA">Washington</option>
</optgroup>
</select>

None of the answers satisfied me. Created a new version of the select helper that accepts group names:
#(field: play.api.data.Field, options: Seq[(String, Seq[(String,String)])], args: (Symbol,Any)*)(implicit handler: helper.FieldConstructor, messages: play.api.i18n.Messages)
#helper.input(field, args:_*) { (id, name, value, htmlArgs) =>
#defining( if( htmlArgs.contains('multiple) ) "%s[]".format(name) else name ) { selectName =>
#defining( field.indexes.nonEmpty && htmlArgs.contains('multiple) match {
case true => field.indexes.map( i => field("[%s]".format(i)).value ).flatten.toSet
case _ => field.value.toSet
}){ selectedValues =>
<select id="#id" name="#selectName" #toHtmlArgs(htmlArgs)>
#args.toMap.get('_default).map { defaultValue =>
<option class="blank" value="">#defaultValue</option>
}
#options.map { case (groupName, elements) =>
<optgroup label="#groupName">
#elements.map { case (k, v) =>
#defining( selectedValues.contains(k) ) { selected =>
#defining( args.toMap.get('_disabled).exists { case s: Seq[String] => s.contains(k) }){ disabled =>
<option value="#k"#if(selected){ selected="selected"}#if(disabled){ disabled}>#v</option>
}
}
</optgroup>
}}
</select>
}}
}
(Use lang : play.api.i18n.Lang instead of messages: play.api.i18n.Messages for Play versions prior to 2.4).
You can use this helper this way:
#groupSelect(
form("brand"),
Seq(
"Swedish Cars" -> Seq(
"volvo" -> "Volvo",
"saab" -> "Saab"
),
"German Cars" -> Seq(
"mercedes" -> "Mercedes",
"audi" -> "Audi"
)
)
)
And it will render this:
<select id="brand" name="brand">
<optgroup label="Swedish Cars">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
</optgroup>
<optgroup label="German Cars">
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</optgroup>
</select>

Here is my working solution:
<div class="clearfix #if(MedicalIncidentForm("incidentType.id").hasErrors) {error}">
<label class="note note-title note-#if(MedicalIncidentForm("incidentType.id").hasErrors) {error} else {success}" for="incidentType_id">Rodzaj</label>
<div class="input note note-footer note-#if(MedicalIncidentForm("incidentType.id").hasErrors) {error} else {success}">
<select name="incidentType.id" onchange="checkSelectedValue(this)">
<option></option>
#for(opt <- new IncidentType().getOptionGroups()) {
<optgroup label="#opt._1">
#for(op <- opt._2) {
#**
<option value="#op._1">#op._2</option>
**#
<option value="#op._1" #if(MedicalIncidentForm("incidentType.id").value() == op._1) {selected="selected"}>#op._2</option>
}
</optgroup>
}
</select>
</div>
</div>

Look at the select helper in scala : https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/views/helper/select.scala.html
There is no mention of optgroup so I think the answer is no. Anyway, you can create a helper of your own by copying the code and customize it so that it is integrating the optgroups. For example this is my code for my custom input text. I had to removw implicit i18n language because of a bug :
#(field: play.api.data.Field, args: (Symbol,Any)*)(implicit handler: views.html.helper.FieldConstructor)
#inputType = #{ args.toMap.get('type).map(_.toString).getOrElse("text") }
#inputClass = #{ args.toMap.get('class).map(_.toString) }
#helper.input(field, args.filter(_._1 != 'type).filter(_._1 != 'class):_*) { (id, name, value, htmlArgs) =>
<input type="#inputType" id="#id" class="form-control #inputClass" name="#name" value="#value" #toHtmlArgs(htmlArgs)/>
}

Related

testing library userEvent.selectOptions does not select option

I have a React component which renders a combobox (another external component) with an option. When deployed the component does work as expected.
<select class="country-select"
id="nationalityCode" name="nationalityCode" required="">
<option value="" disabled="" hidden="">Choose</option>
<optgroup label="Most used">
<option value="0052">Belgium</option>
<option value="0055">German Citizien</option>
<option value="0057">French</option>
<option value="0001">Dutch</option>
</optgroup>
<optgroup label="Alle Nationalities">
<option value="0052">Belgium</option>
<option value="0055">German Citizien</option>
<option value="0057">French</option>
<option value="0001">Dutch</option>
<option value="0050">Albanese</option>
<option value="0223">American Citizen</option>
</optgroup>
</select>
When using testing library userEvent.selectOptions, the select of an option is successfull. Only the expect fails with
Error: expect(received).toBe(expected) // Object.is equality
Expected: true
Received: false
When debugging the selection state for all options it shows that the initial selected option is selected.
if (changeValue.nationaliteit) {
const selectOption = screen.getAllByRole('option', { name: 'French' })[0];
await userEvent.selectOptions(
screen.getByRole('combobox', { name: 'Nationaliteit' }),
selectOption
);
expect(
(screen.getAllByRole('option', { name: 'French' })[0] as HTMLOptionElement).selected
).toBe(true);
}
Using
"#testing-library/user-event": "^14.4.3",
"#testing-library/jest-dom": "^5.16.5",
"#testing-library/react": "^12.1.5",

Add optgroup dynamically to an existing select

I have an existing select with 5 options and a default blank value. I want to add an optgroup to the first 3 values and another optgroup to the last two options.
<select id="cityDropdown">
<option selected="selected" value="" label=" "> </option>
<option value="1000">Tokyo</option>
<option value="1001">Kyoto</option>
<option value="1002">Osaka</option>
<option value="1003">Incheon</option>
<option value="1004">Busan</option>
</select>
I want my select to look like this
<select id="cityDropdown">
<optgroup label="Japan">
<option value="1000">Tokyo</option>
<option value="1001">Kyoto</option>
<option value="1002">Osaka</option>
</optgroup>
<optgroup label="SoKorea">
<option value="1003">Incheon</option>
<option value="1004">Busan</option>
</optgroup>
</select>
Below is my existing code which no longer works since the values are no longer even.
$(document).ready(function() {
var select = $('#cityDropdown');
var opt1, opt2;
$('option', select).each(function(i) {
if (i % 2 === 0) {
opt1 = $(this);
} else {
opt2 = $(this);
var optgroup = $('<optgroup/>');
optgroup.attr('label', label);
opt2.add(opt1).wrapAll(optgroup);
}
});
});

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>

Display textbox after selection of option

I'm making a form at the moment and I was wondering how I could get the script to show a textbox after I have selected options "other" or "option 3".
HTML:
<select name="choice" onchange="if(this.selectedIndex==5)
{this.form['other'].style.visibility='visible'}else
{this.form['other'].style.visibility='hidden'};">
<option value="" selected="selected">Select...</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="other">Other</option>
</select>
<input type="textbox" name="other" style="visibility:hidden; margin-left:3px"/>
Javascript:
window.addEvent('domready', function() {
$('hearabout').addEvent('change', function() {
if ($('hearabout').value == 'Rekening' ) {
$('other_input').setStyle('display', 'block');
} else {
$('other_input').setStyle('display', 'none');
}
});
if ($('hearabout').value == 'Rekening' ) {
$('other_input').setStyle('display', 'block');
} else {
$('other_input').setStyle('display', 'none');
}
});
How do I change "this.selectedIndex==5" so that it takes both option 3 and 5?
Thanks
Add ID for ur select <select id='someth'>
Add an event for changing the selected value:
$('#someth').on('change', function(){
if (('#someth').val() == "other")
{
$('#YourInputID').css('display','block');
}
});
Dont miss to add display:none; in the input style

Fetch records count using PHP and MongoDB

I have an HTML page with a department selectbox. when end user selects any department I have no show him the no of employs in that department. The employee collect
<select multiple="" class="chosen-select choice" id="form-field-select-4" data-placeholder="Choose a Department..." onchange="show_employee_count(this.value)">
<option value="Management">Senior Management</option>
<option value="Legal">Legal</option>
<option value="Operations">Operations</option>
<option value="Administration">Administration</option>
<option value="R&D">R&D</option>
<option value="Sales & Marketing">Sales & Marketing</option>
<option value="Finance">Finance</option>
<option value="Technology">Technology</option>
<option value="Customer Service">Customer Service</option>
<option value="Pro Services">Pro Services</option>
<option value="HR">HR</option>
</select>
The count of employee to show in this container div
<div id="emp_count"></div>
I have tried this as :
HTML
<select name='department' id='department'>
<option value="Management">Senior Management</option>
<option value="Legal">Legal</option>
<option value="Operations">Operations</option>
<option value="Administration">Administration</option>
<option value="R&D">R&D</option>
<option value="Sales & Marketing">Sales & Marketing</option>
<option value="Finance">Finance</option>
<option value="Technology">Technology</option>
<option value="Customer Service">Customer Service</option>
<option value="Pro Services">Pro Services</option>
<option value="HR">HR</option>
</select>
<div id="leads_coount"></div>
JS Code
<script type="text/javascript">
$(function(){
$("#department").change(function(){
var selectedDepartment = $(this).find(":selected").val();
console.log("the department you selected: " + selectedDepartment);
$.ajax({
type: "POST",
url: "ajax.php",
cache: false,
data: { method: "get_lead_count", department: selectedDepartment }
})
.done(function( leads ) {
$( "#leads_coount" ).html(leads);
}).fail(function( jqXHR, textStatus ) {
alert( "Request failed: " + textStatus );
});
});
});
</script>
ajax.php
<?php require_once('DataAccessBean.class.php');
if($_POST['method'] == 'get_lead_count') {
// select a collection
$collection = new MongoCollection($db, 'employs');
// find the collections with department
$clause = array('Department' => $_POST['department']);
$cursor = $collection->find($clause)->count();
echo 'There are '.$cursor.' employees available in this department';
//echo $_POST['department'];
}
Is there a better way to do?