Dependent drop-down list from map in Thymeleaf - javascript

I want to create a drop-down list with countries and the second drop-down list with cities, which depends on selected value in the first list. And the list of cities should be changed dynamically.
In the view (Thymeleaf) I have a Map<CountryModel, Set<RegionModel>> from controller. CountryModel's name should be shows in the second drop-down list, and Set should be shows in the second(dependent) drop-down list.
Here I create first drop-down list:
<tr>
<td th:text="#{country}"/>
<td>
<div class="form-group">
<select th:field="*{transferRequestModel.country}" class="form-control" id="country">
<option th:each="country : ${transferModel.countries}"
th:value="${country}"
th:text="${country.key.countryName}">Wireframe
</option>
</select>
</div>
</td>
</tr>
So how to create second drop-down list which depends on selected country in the first list?

So I have solved my problem with AJAX request and jQuery append.
Change Map<CountryModel, Set<RegionModel>> to Map<String, Set<String>>
AJAX request
function sendAjaxRequest() {
var country = $("#country").val();
$.get( "/regions?country=" + country, function( data ) {
$("#region").empty();
data.forEach(function(item, i) {
var option = "<option value = " + item + ">" + item + "</option>";
$("#region").append(option);
});
});
};
Use sendAjaxRequest() when i change first drop-down list.
$(document).ready(function() {
$("#country").change(function() {
sendAjaxRequest();
});
});
Drop-down list at the Thymeleaf template
First drop-down list
<td th:text="#{country}"/>
<td>
<div class="form-group">
<select th:field="*{model.country}" class="form-control" id="country">
<option th:each="country : ${model.countries}"
th:value="${country}"
th:text="${country}">Wireframe
</option>
</select>
</div>
</td>
Second drop-down list
<td>
<div class="form-group">
<select th:field="*{requestModel.region}" class="form-control" id="region">
</select>
</div>
</td>
Controller
#RequestMapping(value = "/regions")
#ResponseBody
public Set getRegions(#RequestParam String country) {
Map<String, Set<String>> regions = regionsService.getRegions();
return regions.get(country);
}

In our project we did it like that:
<div class="form-group">
<label class="col-sm-4 control-label"
th:text="#{person.edit.policy.tfoms}"></label>
<div class="col-sm-8">
<select class="form-control" th:field="*{tfoms}"
onchange="loadInsuranceCompanies()">
<option th:each="t : ${tfomses}"
th:value="${t.uidtfoms}"
th:text="${t.shortName}"
th:selected="${personBean.tfoms != null
and personBean.tfoms.equals(t)}">
</option>
</select>
</div>
</div>
<div th:class="${#fields.hasErrors('insuranceCompany')}
? 'form-group has-error' : 'form-group'">
<label class="col-sm-4 control-label"
th:text="#{person.edit.policy.ic}">
</label>
<div class="col-sm-8" id="insuranceCompaniesContent">
<select class="form-control" id="insuranceCompany"
name="insuranceCompany"
th:fragment="insuranceCompany">
<option th:each="i : ${insuranceCompanies}"
th:value="${i.uidinsurancecompany}"
th:text="${i.shortName}"
th:selected="${personBean.insuranceCompany != null
and personBean.insuranceCompany.equals(i)}">
</option>
</select>
<div th:if="${#fields.hasErrors('insuranceCompany')}"
th:each="err : ${#fields.errors('insuranceCompany')}">
<span class="text-danger" th:text="${err}"></span><br/>
</div>
</div>
</div>
Insurance companies loading function loadInsuranceCompanies():
function loadInsuranceCompanies() {
var url = /*[[#{/PersonEdit/insuranceCompanies}]]*/ "/PersonEdit/insuranceCompanies";
if ($('#tfoms').val() !== '') {
url = url + '/' + $('#tfoms').val();
}
$("#insuranceCompaniesContent").load(url);
}
And finally code in controller:
#RequestMapping(value = "/PersonEdit/insuranceCompanies/{tfoms}", method = RequestMethod.GET)
public String getInsuranceCompaniesByTfoms(#PathVariable("tfoms") Integer tfomsId,
Model model) {
model.addAttribute("insuranceCompanies", insuranceCompanyService
.getInsuranceCompaniesByTfoms(new TerritorialFondOms(tfomsId)));
return "person/PersonEdit :: insuranceCompany";
}

Related

Drop down when select the option from ajax another input field appear

Hi i needed some help where if i select a drop down and select from ajax option and a hidden input field appear how can i do it ?
<div class="form-row">
<div class="col">
<label for="select-price-mode" class="col-form-label">Price Mode</label>
<select class="select-price-mode custom-select-sm col-10" id="select-price-mode" required>
<option selected disabled value="">Select ....</option>
</select>
</div>
<div class="col" hidden>
<label for="select-payment-frequency" class="col-form-label">Payment Frequency</label>
<select class="select-payment-frequency custom-select-sm col-10" id="select-payment-frequency" required>
<option selected disabled value="">Select ....</option>
</select>
</div>
This is my ajax
// Here the calling Ajax for the drop down menu below
$.ajax({
// The url that you're going to post
/*
This is the url that you're going to put to call the
backend api,
in this case, it's
https://ecoexchange.dscloud.me:8080/api/get (production env)
*/
url:"https://ecoexchange.dscloud.me:8090/api/get",
// The HTTP method that you're planning to use
// i.e. GET, POST, PUT, DELETE
// In this case it's a get method, so we'll use GET
method:"GET",
// In this case, we are going to use headers as
headers:{
// The query you're planning to call
// i.e. <query> can be UserGet(0), RecyclableGet(0), etc.
query:"PriceModeGet()",
// Gets the apikey from the sessionStorage
apikey:sessionStorage.getItem("apikey")
},
success:function(data,textStatus,xhr) {
console.log(data);
for (let option of data) {
$('#select-price-mode').append($('<option>', {
value: option.PriceMode,
text: option.PriceMode
}));
}
},
error:function(xhr,textStatus,err) {
console.log(err);
}
});
and this is my ajax response
[
{
"PriceMode": "Price By Recyclables"
},
{
"PriceMode": "Service Charger"
}
]
Where say if i select Price By Recyclables the hidden drop down list appear how can i do it ?
You can use the onchange event to trigger a check and if the user selected the value you want, then display the selectbox. You'd have to add an id to the div with the hidden prop (divToDisplay).
$("#select-price-mode").change(function() {
if(this.value === "Price By Recyclables") {
$('#divToDisplay').removeAttr('hidden');
}
});
Just invoke a function when an option is selected in first select
const checkPriceMode = () => {
let value = $('.select-price-mode').val();
$('.payment-frequency').fadeOut();
if(value === 'Price By Recyclables') $('.payment-frequency').fadeIn();
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-row">
<div class="col">
<label for="select-price-mode" class="col-form-label">Price Mode</label>
<select onchange="checkPriceMode()" class="select-price-mode custom-select-sm col-10" id="select-price-mode" required>
<option selected disabled value="">Select.....</option>
<option value="Price By Recyclables">Price By Recyclables</option>
<option value="Service Charger">Service Charger</option>
</select>
</div>
<div class="col payment-frequency" hidden>
<label for="select-payment-frequency" class="col-form-label">Payment Frequency</label>
<select class="select-payment-frequency custom-select-sm col-10" id="select-payment-frequency" required>
<option selected disabled value="">Select ....</option>
</select>
</div>

Selecting a specific element from multiple forms

I'm trying to select a specific element from multiple forms but it's not working properly:
So my javascript code is:
function makeActive(target)
{
$("div.interactive").removeClass("interactive");
$("#form" + target).addClass("interactive");
}
$(document).ready(function () {
$('.interactive option[name=bu]').on('change', function () {
$('.interactive option[name=discipline]').empty();
$('.interactive option[name=project]').empty();
$('.interactive option[name=role]').empty();
$.ajax({
type: 'GET',
url: '#Url.Action("GetList", "Central")',
dataType: 'Json',
data: { InitiateId: $('.interactive option[name=bu]').val(), InitiateType: "BU" },
success: function (data) {
console.log("That was calling")
$('.interactive option[name=discipline]').append('<option value="">Select</option>');
$.each(data, function (index, value) {
$('.interactive option[name=discipline]').append('<option value="' + value.Id + '">' + value.Name + '</option>');
});
$('.interactive option[name=project]').append('<option value="">Select Discipline firt</option>');
$('.interactive option[name=role]').append('<option value="">Select Project first</option>');
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
});
And cshtml struct page is:
<div id="faq" role="tablist" aria-multiselectable="true">
#foreach (var actor in Model)
{
string areacontrol = "answer" + actor.Id;
count +=1;
bool open = false;
if (ViewBag.actor != null)
{
if (actor.Id == ViewBag.actor.Id)
{
open = true;
}
}
else
{
if (count == 1)
{
open = true;
}
}
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="questionOne">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#faq" href="##areacontrol" aria-expanded="false" aria-controls="answerOne"
onclick=" makeActive(#actor.Id)">
#actor.Name (#actor.Email)
</a>
</h5>
</div>
<div id="#areacontrol" class="panel-collapse collapse #(open?" in":"")" role="tabpanel" aria-labelledby="questionOne">
<div class="panel-body">
#using (Html.BeginForm("Assign", "Central", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
string form = "form" + actor.Id;
<div class="row form-group #(open?" interactive":"")" id="#form">
<div class="col-md-3 col-md-offset-0">
<label for="bu">Business Unit</label>
<select name="bu" class="form-control">
<option value="">--Select--</option>
#foreach (var item in flowcontext.ContiBusinessUnits.ToList())
{
if (ViewBag.bu != null && actor.Id == ViewBag.actor.Id)
{
bool selected = false;
if (ViewBag.bu.Name == item.Name)
{
selected = true;
}
if (selected)
{
<option value="#item.Id" selected>#item.Name</option>
}
else
{
<option value="#item.Id">#item.Name</option>
}
}
else
{
<option value="#item.Id">#item.Name</option>
}
}
</select>
</div>
<div class="col-md-3">
<label for="discipline">Discipline</label>
<select name="discipline" class="form-control">
#if (ViewBag.discipline != null && actor.Id == ViewBag.actor.Id)
{
<option value="#ViewBag.discipline.ID">#ViewBag.discipline.Name</option>
}
else
{
<option value="">Select Business Unit first</option>
}
</select>
</div>
<div class="col-md-3">
<label for="project">Project</label>
<select name="project" class="form-control">
#if (ViewBag.project != null && actor.Id == ViewBag.actor.Id)
{
<option value="#ViewBag.project.ID">#ViewBag.project.Name</option>
}
else
{
<option value="">Select Discipline first</option>
}
ViewBag.role_id = contiRole;
</select>
</div>
<div class="col-md-3">
<label for="destination">Role</label>
<select name="role" class="form-control">
#if (ViewBag.role != null && actor.Id == ViewBag.actor.Id)
{
<option value="#ViewBag.role.ID">#ViewBag.role.Name</option>
}
else
{
<option value="">Select Project first</option>
}
</select>
</div>
<div class="col-md-3" style="display:none">
<label for="destination">User Id</label>
<select name="userid" class="form-control">
<option value="#actor.Id" selected>#actor.Name</option>
</select>
</div>
</div>
<div class="row form-group">
<div class="col-md-3 col-md-offset-8">
<input type="submit" class="btn btn-primary btn-block" value="Add">
</div>
</div>
}
</div>
</div>
</div>
}
</div>
<!--end language: lang-html -->
In that inside a foreach loop, I load/ generate a form.
First: The bootstrap collapse will be open for the first user(actor);
Inside, I have a form with is necessary to be similar and be a cascade drop select!
When I make a change[ $('.interactive option[name=bu]').on('change', function (){}]that calls for me a controller method which returns me a list and with that list a generate the second field and again for other 2 field!
That helps me to make a cascade select for a form and that works well but only for the first one!
I think either I'm not making the selections properly or using ajax, "$ (document) .ready" does not get the data properly.
How I can select properly or tell others methods!
How can improve that and make it work for all form elements?
Hi in this example we get the selected value from a dropdown list in different forms using a commun class the elements share and then we save that value inside an array which contains the name of the dropdown list, the selected value and the selected value text.
let options = document.querySelectorAll('.cmbMsg');
//get all select boxes with the same class
var values = [];
options.forEach(function(option) {
values.push({"item":option.getAttribute("name"),"value":option[option.selectedIndex].value,"text":option[option.selectedIndex].text});
});
console.log(values);
.cmbMsg {
font-size:14px;
}
<form action="" id="form1">
<select name="select1" id="select1" class="cmbMsg">
<option value="1" selected>Hello </option>
<option value="2">My friend</option>
</select>
</form>
<br>
<form action="" id="form2">
<select name="select2" id="select2" class="cmbMsg">
<option value="1">Hola</option>
<option value="2" selected>Mundo</option>
</select>
</form>
<br>
<form action="" id="form3">
<select name="select3" id="select3" class="cmbMsg">
<option value="1">Viva</option>
<option value="2" selected>la France</option>
</select>
</form>
Hope it helps
I found the solution!
The problem was that I did not recognize my selections after we came up with a change using ajax and I just load all my field immediately after the page load and group them for each form!
$(form + 'select[name=bu]').on('change', function (){};
And I just call a function for getting all actorid and pushing on a list and "leasing" for all field;

dynamic row creation affecting other created dropdown values angular 6

I have 3 drop downs primary, secondary,ternary categories, each dependent on each other, Initially I have 3 drop downs below that I have one button " add more" , after clicking "add more" again drops will come below the ones earlier have, now the question is first row drop down selection is working fine , after clicking "add more" the second row drop down selection is not working , means it changes the value of already selected first row of the second category same with the ternary category. first I all load all the primary category, based on primary id i will fetch secondary categories, based on the secondary category id i will fetch ternary category. please me with this.
HTML CODE
<div class="row Space_2">
<div class="col-md-4">
<select class="Textfield_2" id="primary_category_id" formControlName="primary_category_id" (change)="getSecondCategory($event.target.value)" name="primaryServices" required>
<option value="">Primary Service</option>
<option *ngFor="let primaryCat of primaryCategory" [value]="primaryCat.id">{{primaryCat.name}}</option>
</select>
</div>
<div class="col-md-4">
<select class="Textfield_2" id="secondary_category_id" formControlName="secondary_category_id" (change)="getTernaryCategory($event.target.value)" name="secondaryServices" required>
<option value="">Secondary Service</option>
<option *ngFor="let secondCat of secondCategory" [value]="secondCat.id">{{secondCat.name}}</option>
</select>
</div>
<div class="col-md-4">
<select class="Textfield_2" id="ternary_category_id" formControlName="ternary_category_id" name="secondaryServices" required>
<option value="">Ternary Service</option>
<option *ngFor="let ternaryCat of ternaryCategory" [value]="ternaryCat.id">{{ternaryCat?.name}}</option>
</select>
</div>
</div>
<div *ngFor="let k of addmoreServices let i = index">
<div class="row Space_2">
<div class="col-md-4">
<select class="Textfield_2" id="primary_category" (change)="getSecondCategory($event.target.value)" name="{{k.primary_category}}" required>
<option value="">Primary Service</option>
<option *ngFor="let a of primaryCategory" [value]="a.id">{{a?.name}}</option>
</select>
</div>
<div class="col-md-4">
<select class="Textfield_2" id="secondary_category" (change)="getTernaryCategory($event.target.value)" name="{{k.secondary_category}}" required>
<option value="">Secondary Service</option>
<option *ngFor="let b of secondCategory" [value]="b.id">{{b?.name}}</option>
</select>
</div>
<div class="col-md-4">
<select class="Textfield_2" id="secondary_category" (change)="getTerId($event.target.value)" name="{{k.ternary_category}}" required>
<option value="">Ternary Service</option>
<option *ngFor="let c of ternaryCategory" [value]="c.id">{{c?.name}}</option>
</select>
</div>
</div>
</div>
TypeScript Code:
getPrimaryCategory() {
this.http.get('http://localhost:3000/api/getPrimaryCategory' ,{
})
.subscribe(
res => {
this.primaryCategory = res['data'];
console.log(this.primaryCategory);
},
err => {
}
);
}
getSecondCategory(id,i) {
this.primcatId = id;
this.http.get('http://localhost:3000/api/getsecondarycatdataforternary/'+id ,{
})
.subscribe(
res => {
this.secondCategory = res['data'];
console.log(this.secondCategory);
},
err => {
}
);
}
getTernaryCategory(id) {
console.log("The ternary ID is",id);
this.secondId = id;
this.http.get('http://localhost:3000/api/getternaryCatforServices/'+id ,{
})
.subscribe(
res => {
this.ternaryCategory = res['data'];
console.log(this.ternaryCategory);
},
err => {
}
);
}
getTerId(id){
this.terid = id;
console.log("THE TERNARY ID IS",this.terid);
}
addMoreServices() {
this.addmoreServices.push({ primary_category:this.primcatId , secondary_category:this.secondId ,ternary_category: this.terid });
console.log("the add more services",this.addmoreServices);
}
You need to add trackBy to your *ngFor directives. You can track by id and thanks you this Angular won't treat values after refreshing as new values.

Laravel chained dropdown selection using jquery ajax

I'm using laravel 5.6 and I've made dropdown selection but it didn't work. I choosed a province in dropdown menu provinces but the menu city not shown up the data of cities.
This is my controller :
public function province()
{
$prov = Province::orderBy("provinsi.id","ASC")
->pluck("name","id");
return view('auth.register',compact('prov'));
}
public function cities($id)
{
$city = City::where("id_provinsi","=",$id)
->pluck("city_name","id");
return json_encode($city);
}
This is my route:
Route:: get('/register', 'Auth\RegisterController#province');
Route:: get('/register/cities/{id}', 'Auth\RegisterController#cities');
This is my view:
<div class="form-group row">
<label for="prov" class="col-md-4 col-form-label text-md-right">{{ __('Provinsi') }}</label>
<div class="col-md-6">
<select name="prov" class="form-control">
<option value="">=== Choose Province ===</option>
#foreach ($prov as $key=>$value)
<option value="{{$key}}">{{$value}}</option>
#endforeach
</select>
</div>
</div>
<div class="form-group row">
<label for="city" class="col-md-4 col-form-label text-md-right">{{ __('City') }}</label>
<div class="col-md-6">
<select name="cities" class="form-control"> </select>
</div>
</div>
This is my javascript:
<script type="text/javascript">
$(document).ready(function()
{
$('select[name="prov"]').on('change', function() {
var provID = $(this).val();
if(provID) {
$.ajax({
url: '/register/cities/'+provID,
type: "GET",
dataType: "json",
success:function(data) {
$('select[name="cities"]').empty();
$.each(data, function(key, value) {
$('select[name="cities"]').append('<option value="'+ key +'">'+ value +'</option>');
});
}
});
}else{
$('select[name="cities"]').empty();
}
});
});
</script>
I got the data json if I open the url /register/cities/(any province id) .
Make sure the response returned in
public function cities($id) { ... }
is in JSON format.
To do this check network log in your browser (in Firefox o Chrome F12 -> Net:XHR -> Response) or add a colsole.log(data) in the success callback.
in your view replace you second select
<select name="cities" class="form-control" id='cities'> </select>
your first select change this
<select name="prov" class="form-control">
<option value="">=== Choose Province ===</option>
#foreach ($prov as $key=>$value)
option value="{{$value->id}}">{{$value->name}}</option>
#endforeach
</select>
next changue in your controller
public function cities($id)
{
$city = City::where("id_provinsi",$id)->get()
return response()->json(['cities' => $city], 200);
}
changue this in your each inside ajax
$.each(data.cities, function(key, value) {
$('#cities').append('<option value="'+ value.id+'">'+ value.name +'</option>');
});
changue your url ajax for this
url:"{{ url('/register/cities/') }}/"+provID;
public function cities($id)
{
$city = City::where("id_provinsi","=",$id)
->pluck("city_name","id");
$html = view('city_list', compact('city'))->render();
return response()->json([
'html' => $html
]);
}
city_list.blade.php
<select name="city" class="form-control">
<option value="">=== Choose City===</option>
#foreach ($city as $key=>$value)
<option value="{{$key}}">{{$value}}</option>
#endforeach
</select>

Angular 5 how to bind drop-down value based on another drop-down

I have a select drop-down that i populate from an api, i want to be able to populate a second select drop-down based on the user's first choice and subsequently populate a second drop-down based on the user's second choice.
Say i have my input fields so
form.component.html
<div class="form-group col-sm-6">
<label> Category</label>
<select class="form-control" [(ngModel)]="product.productCategory" [formControl]="productForm.controls['productCategory']" require>
<option *ngFor="let item of categorys" [value]="item.slug">{{item.name}}</option>
</select>
</div>
<div class="form-group col-sm-6">
<label> Product Type</label>
<select class="form-control" [(ngModel)]="product.productType" [formControl]="productForm.controls['productType']" require>
<option *ngFor="let item of productTypes" [value]="item.slug">{{item.name}}</option>
</select>
</div>
<div class="form-group col-md-6">
<label>Sub-Category</label>
<select class="form-control" [(ngModel)]="product.subCategory" [formControl]="productForm.controls['subCategory']" require>
<option *ngFor="let item of subs" [value]="item.slug">{{item.name}}</option>
</select>
</div>
As it is i am binding the whole list to each individual select drop-down but i want the subCategory to be only those under the selected category and same then productType based on the subCategory selected.
This is how i retrieve the category as it is the parent selection
form.component.ts
fetchCategorys() {
this.categorySrv.fetchCategories().then((response: any) => {
this.categorys = response;
console.log(this.categorys);
})
.catch(error => this.error = error)
}
I am using same method to get the subCategory and productType respectively. As you can see it brings all the items in each section from db but i want to be able to bind subCategory based on the choice of category and also bind productType based on the choice of subCategory.
Note that console.log(this.categorys) displays the category with their respective subCategory and productType but i can't figure out how to make the binding correspond.
Template
<div class="form-group col-sm-6">
<label> Category</label>
<select class="form-control" (change)="categoryChange($event)" [(ngModel)]="product.productCategory" [formControl]="productForm.controls['productCategory']" require>
<option *ngFor="let item of categorys" [value]="item.slug">{{item.name}}</option>
</select>
</div>
<div class="form-group col-sm-6">
<label> Product Type</label>
<select class="form-control" (change)="productTypeChanged($event)" [(ngModel)]="product.productType" [formControl]="productForm.controls['productType']" require>
<option *ngFor="let item of productTypes" [value]="item.slug">{{item.name}}</option>
</select>
</div>
<div class="form-group col-md-6">
<label>Sub-Category</label>
<select class="form-control" [(ngModel)]="product.subCategory" [formControl]="productForm.controls['subCategory']" require>
<option *ngFor="let item of subs" [value]="item.slug">{{item.name}}</option>
</select>
</div>
Component
public allProductTypes: ProductType[];
public allSubs: Category[];
public categoryChange( $event: Category ) {
this.productTypes = this.allProductTypes.filter( _productType => _productType.belongsTo( $event));
}
public productTypeChanged( $event: ProductType ) {
this.subs = this.allSubs.filter( _sub => _sub.belongsTo( $event ) );
}
So you bind your to the dropdown change events. Then, each time a category or product type is chosen, we filter the data that the dropdowns have available to show.
You will also probably have to reset the downstream choices, aka. when changing category, then reset product type and sub cat, because the new top level category might not allow for the old type and subcat values to exist.

Categories

Resources