I am having a terrible time wrapping my head around arrays for Vue JS.
new Vue({
el: '#app',
template: `
<div class="cascading-dropdown">
<div class="dropdown">
<span>Cereal:</span>
<select v-model="cerealname">
<option value="">SELECT A CEREAL</option>
<option v-for="(addon1_obj, addon1) in cereals" :value="addon1">{{addon1}}</option>
</select>
</div>
<div class="dropdown">
<span>Addon 1:</span>
<select :disabled="addons1.length == 0" v-model="addon1">
<option value="">Select Addon 1</option>
<option v-for="(addon2_obj, addon2) in addons1">{{addon2}}</option>
</select>
</div>
<div class="dropdown">
<span>Addon 2:</span>
<select :disabled="addons2.length == 0" v-model="addon2">
<option value="">Select Addon 2</option>
<option v-for="addon2 in addons2">{{addon2}}</option>
</select>
</div>
<div class="dropdown">
<span>Addon 3:</span>
<select :disabled="addons2.length == 0" v-model="addon3">
<option value="">Select Addon 3</option>
<option v-for="addon2 in addons2">{{addon2}}</option>
</select>
</div>
<div>Addon 1 text <input id="addon1desc" type="text" v-midel="addon1desc"></div>
<div>Addon 2 text <input id="addon2desc" type="text" v-midel="addon2desc"></div>
<div>Addon 3 text <input id="addon3desc" type="text" v-midel="addon3desc"></div>
</div>
`,
data: function() {
return {
cereals: {
"Lucky Charms": {
"Marshmallows": ["Green Clovers",
"Pink Hearts",
"Yellow Moons",
"Blue Diamonds",
"Purple Horseshoes"
]
},
"Froot Loops": {
"Loops": ["Red Loop",
"Green Loop",
"Blue Loop",
"Yellow Loop"
]
}
},
addons1: [],
addons2: [],
cerealname: "",
addon1: "",
addon2: "",
addon3: ""
}
},
watch: {
cerealname: function() {
// Clear previously selected values
this.addons1 = [];
this.addons2 = [];
this.addon1 = "";
this.addon2 = "";
this.addon3 = "";
// Populate list of countries in the second dropdown
if (this.cerealname.length > 0) {
this.addons1 = this.cereals[this.cerealname]
}
},
addon1: function() {
// Clear previously selected values
this.addons2 = [];
this.addon2 = "";
this.addon3 = "";
// Now we have a continent and country. Populate list of cities in the third dropdown
if (this.addon1.length > 0) {
this.addons2 = this.cereals[this.cerealname][this.addon1]
}
}
}
})
.dropdown {
margin: 10px 0;
padding: 10px 0;
border-bottom: 1px solid #DDD;
}
.dropdown span {
display: inline-block;
width: 80px;
}
<body>
<div id="app"></div>
</body>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
Here's a fiddle: https://jsfiddle.net/4zfh80au/
When you select Lucky Charms in the first dropdown, the 2nd dropdown changes to Marshmallows. The 3rd and 4th dropdowns change to the individual marshmallow types.
What I want is to add data to the text boxes based on the dropdown selection. When you choose the 2nd dropdown to be Marshmallows, I want the corresponding text box to fill in some text like "Marshmallows are yummy." The 3rd and 4th dropdowns should do the same.
Could anyone please point me in the right direction?? Much appreciated.
The binding is already set up in each of your <select> tags with v-model="addon1", addon2, and addon3.
In your <div>, have the bindings in the text fields match the ones defined in your <select> tags like so:
...
<div class="dropdown">
<span>Addon 1:</span>
<select :disabled="addons1.length == 0" v-model="addon1">
<option value="">Select Addon 1</option>
<option v-for="(addon2_obj, addon2) in addons1">{{addon2}}</option>
</select>
</div>
<div class="dropdown">
<span>Addon 2:</span>
<select :disabled="addons2.length == 0" v-model="addon2">
<option value="">Select Addon 2</option>
<option v-for="addon2 in addons2">{{addon2}}</option>
</select>
</div>
<div class="dropdown">
<span>Addon 3:</span>
<select :disabled="addons2.length == 0" v-model="addon3">
<option value="">Select Addon 3</option>
<option v-for="addon2 in addons2">{{addon2}}</option>
</select>
</div>
<div>Addon 1 text <input id="addon1desc" type="text" v-model="addon1"></div>
<div>Addon 2 text <input id="addon2desc" type="text" v-model="addon2"></div>
<div>Addon 3 text <input id="addon3desc" type="text" v-model="addon3"></div>
</div>
...
You can check out the working fiddle here.
Additionally, the fiddle link that you shared had a typo in v-model. If you run the app, you should see an error thrown into the console that says something like this:
[Vue warn]: Failed to resolve directive: midel
(found in anonymous component - use the "name" option for better debugging messages.)
If something in the app is failing, you can use the console to better debug your code.
For anyone wanting the solution, the Fiddle is here:
https://jsfiddle.net/q1jm0ccf/
The array looks as follows:
data: function() {
return {
cereals: {
"Lucky Charms": {
"Marshmallows": [
{"title": "Green Clovers", "value": "The Green Clovers is nice"},
{"title":"Pink Hearts", "value": "The Pink Hearts is cool"},
{"title":"Yellow Moons", "value": "The Yellow Moons is best"},
{"title":"Blue Diamonds","value": "The Blue Diamonds is bad"},
{"title":"Purple Horseshoes","value": "The Purple Horseshoes is normal"},
{"title":"Red","value": "The red ones are great."},
{"title":"Yellow","value": "The yellow ones are better"}
]
},
"Froot Loops": {
"Loops": [
{"title":"Red","value": "Red loops are cherry"},
{"title":"Green","value": "Green loops are lime"}
]
}
},
Related
I have a simple form created using HTML and JS. There are 3 select elements that the options of the second and the third select elements are based on the first select option. The HTML code is below.
<div class="d-flex flex-column">
<label>City</label>
<select name="city" class="city" id="city-selection">
<option selected="selected" value="">Select City</option>
<option value="City 1">City 1</option>
<option value="City 2">City 2</option>
<option value="City 3">City 3</option>
<option value="City 4">City 4</option>
<option value="City 5">City 5</option>
<option value="City 6">City 6</option>
<option value="City 7">City 7</option>
</select>
</div>
<div class="d-flex flex-column">
<label>Hotel</label>
<select name="hotel" class="hotel" id="hotel-selection">
<option selected="selected" value="">Select Hotel</option>
</select>
</div>
<div class="d-flex flex-column">
<label>Tours</label>
<select name="tour" class="tour" id="tour-selection" multiple="multiple">
<option selected="selected" value="">Select Tours</option>
</select>
</div>
The first(#city-selection) and the second(#hotel-selection) select elements are just normal ones. But I changed the third(#tour-selecton) select element as a Bootstrap multi-select element. So the JS part is below.
//City 1 options
var city1Hotels = '<option selected="selected" value="">Select Hotel</option><option value="City 1 Hotel 1">City 1 Hotel 1</option>';
//City 2 options
var city2Hotels = '<option selected="selected" value="">Select Hotel</option><option value="City 2 Hotel 1">City 2 Hotel 1</option>';
var city2Tours = '<option selected="selected" value="">Select Tours</option><option value="City 2 Tour 1">City 2 Tour 1</option><option value="City 2 Tour 2">City 2 Tour 2</option>';
var cityS = $("select#city-selection");
var hotelS = $("select#hotel-selection");
var tourS = $("select#tour-selection");
//changing second and third select elements options based on first select element
$(document).ready(function(){
cityS.on('change',function(){
if($(this).val()=="City 1"){
hotelS.html(city1Hotels); //for hotel results based on a city
}
else if($(this).val()=="City 2"){
hotelS.html(city2Hotels); //for hotel results based on a city
tourS.html(city2Tours); //for tour results based on a city
}
});
});
//set multiselect on third select element
$(function() {
"use strict";
$(document).ready(function() {
$('#tour-selection').multiselect({
includeSelectAllOption: false,});
});
});
The Issue
When I select a city from #city-selection, the #hotel-selection show results properly based on the city entries. But when it comes to #tour-selection, it doesn't show me tours when I selected a city. However, if I remove the multi-select function it shows me all the tours based on the cities. But then the user can select only one option. So it's not my intention and I think the issue with the multi-select. Currently, I have used if-else to change decisions based on the cities. If someone can help me, I'll be much appreciated it!
For More information:
I used this documentation to add bootstrap multi-select. https://davidstutz.github.io/bootstrap-multiselect/
When I add custom options to the third(#tour-selection) select element using HTML to check it, the multi-select feature works properly. But decision-based selection still not working.
I have edited your javascript code using an array of objects to set the data for cities, hotels, and tours to make them dynamically render options
Html
<div class="d-flex flex-column">
<label>City</label>
<select name="city" class="city" id="city-selection">
<option selected="selected" value="">Select City</option>
</select>
</div>
<div class="d-flex flex-column">
<label>Hotel</label>
<select name="hotel" class="hotel" id="hotel-selection">
<option selected="selected" value="">Select Hotel</option>
</select>
</div>
<div class="d-flex flex-column">
<label>Tours</label>
<select name="tour" class="tour" id="tour-selection" multiple="multiple">
<option selected="selected" value="">Select Tours</option>
</select>
</div>
Javascript
//City Options
var cities = ["city-1", "city-2"];
// Hotel options based on cities
var hotels = [
{
city: "city-1",
hotels: ["hotel-1", "hotel-2"],
},
{
city: "city-2",
hotels: ["hotel-1", "hotel-2"],
},
];
// Tour options based on Cities
var tours = [
{
city: "city-1",
tours: ["tour-1", "tour-2"],
},
{
city: "city-2",
tours: ["tour-1", "tour-2"],
},
];
var citySelect = $("select#city-selection");
var hotelSelect = $("select#hotel-selection");
var tourSelect = $("select#tour-selection");
// render city options
for (i in cities) {
if (i == 0) {
// first option with "Select City" as the selected option
citySelect.html(
`<option selected="selected" value="">Select City</option>`
);
citySelect.append(
`<option value="${cities[i]}">${cities[i]}</option>`
);
} else {
// the rest of the options
citySelect.append(
`<option value="${cities[i]}">${cities[i]}</option>`
);
}
}
// changing both hotel options and tour options based on selected city
$(document).ready(function () {
citySelect.on("change", function () {
// render hotel options based on selected city
for (i in hotels) {
if ($(this).val() == hotels[i]["city"]) {
console.log(hotels[i]["city"]);
// first option
hotelSelect.html(
`<option selected="selected" value="">Select Hotels</option>`
);
hotels[i]["hotels"].forEach((hotel) => {
hotelSelect.append(
`<option value="${hotels[i]["city"]}-${hotel}">${hotels[i]["city"]}-${hotel}</option>`
);
});
}
}
// render tour options based on selected city
for (i in tours) {
if ($(this).val() == tours[i]["city"]) {
console.log(tours[i]["city"]);
// first option
tourSelect.html(
`<option selected="selected" value="">Select tours</option>`
);
tours[i]["tours"].forEach((hotel) => {
tourSelect.append(
`<option value="${tours[i]["city"]}-${hotel}">${tours[i]["city"]}-${hotel}</option>`
);
});
}
}
});
tourSelect.on("change", function () {
console.log($(this).val())
})
});
Finally I figure out I can't working with Bootstrap multi-select. That because of it won't let custom JS code replace it's current options in select elements. Otherwise bootstrap-multiselect is a great way to create checkboxes in select elements. There may be a way to override that. But I'm unable to find a way to do that. However I found a another method to fulfill my needs without using Bootstrap multi-select and select element. This answer contains several code lines of multiple stackoverflow answers.
Those answers are,
How to create checkbox inside dropdown?
How to replace all the <li> elements of an <ul> using JQuery?
HTML
First I replace the select element with ul list element as shown in below code.
<div class="d-flex flex-column">
<label>City</label>
<select name="city" class="city" id="city-selection">
<option selected="selected" value="">Select City</option>
<option value="City 1">City 1</option>
<option value="City 2">City 2</option>
<option value="City 3">City 3</option>
<option value="City 4">City 4</option>
<option value="City 5">City 5</option>
<option value="City 6">City 6</option>
<option value="City 7">City 7</option>
</select>
</div>
<div class="d-flex flex-column">
<label>Hotel</label>
<select name="hotel" class="hotel" id="hotel-selection">
<option selected="selected" value="">Select Hotel</option>
</select>
</div>
<div class="d-flex flex-column">
<div id="list1" class="dropdown-check-list">
<label>Select Tours</label>
<span class="anchor">Select Tours</span>
<ul class="tours" id="tour-list">
</ul>
</div>
</div>
CSS
CSS code for dropdown.
.dropdown-check-list {
display: inline-block;
}
.dropdown-check-list .anchor {
position: relative;
cursor: pointer;
display: inline-block;
padding: 5px 50px 5px 10px;
border: 1px solid #ccc;
}
.dropdown-check-list .anchor:after {
position: absolute;
content: "";
border-left: 2px solid black;
border-top: 2px solid black;
padding: 5px;
right: 10px;
top: 20%;
-moz-transform: rotate(-135deg);
-ms-transform: rotate(-135deg);
-o-transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
transform: rotate(-135deg);
}
.dropdown-check-list .anchor:active:after {
right: 8px;
top: 21%;
}
.dropdown-check-list ul.tours {
padding: 2px;
display: none;
margin: 0;
border: 1px solid #ccc;
border-top: none;
}
.dropdown-check-list ul.tours li {
list-style: none;
}
.dropdown-check-list.visible .anchor {
color: #0094ff;
}
.dropdown-check-list.visible .tours {
display: block;
}
JS and JQuery
var city1Tours = ["c1 Tour1","c1 Tour2"];
var city2Tours = ["c2 Tour1","c2 Tour2"];
var city1Hotels = '<option selected="selected" value="">Select Hotel</option><option value="City 1 Hotel 1">City 1 Hotel 1</option>';
var city2Hotels = '<option selected="selected" value="">Select Hotel</option><option value="City 2 Hotel 1">City 1 Hotel 1</option>';
//tour list dropdown js code
var checkList = document.getElementById('list1');
checkList.getElementsByClassName('anchor')[0].onclick = function(evt) {
if (checkList.classList.contains('visible'))
checkList.classList.remove('visible');
else
checkList.classList.add('visible');
}
//hotel selection based on user city decision js code
$(document).ready(function(){
cityS.on('change',function(){
if($(this).val()=="City 1"){
hotelS.html(city1Hotels);
//Tour selection based on the city
$("#tour-list").empty();//This line clears current li contents
$.each(city1Tours, function( key, value ) {
$('#tour-list').append('<li>' + '<input type="checkbox" />' + value + '</li>');
});
}else if($(this).val()=="City 2"){
hotelS.html(city2Hotels);
//Tour selection based on the city
$("#tour-list").empty();//This line clears current li contents
$.each(city2Tours, function( key, value ) {
$('#tour-list').append('<li>' + '<input type="checkbox" />' + value + '</li>');
});
}
});
});
Hope this answer helps someone in future.
I have a button which adds more select drop downs when clicked. So I would like to remove the already selected options in these select boxes for preventing duplication.
The following code is used for the select drop down:
<select class="select form-control"
formControlName="environment_id" (change)="onEnvChange($event.target.value)">
<option selected="selected" disabled value="">Select Environment
</option>
<ng-container *ngFor="let environment of environments">
<option *ngIf="!selectedEnvironments.includes(environment.environment_id)"
[value]="environment.environment_id">
{{environment.environment_id}}</option>
</ng-container>
</select>
and in the component I ave the following function for change
public onEnvChange(selectedEnvironment)
{
this.selectedEnvironments.push(selectedEnvironment);
}
Now when I select an option, that option itself gets removed from the dropdown. For example if I have options like option1,option2,option3 etc, when I select option1, option1 is getting removed from the dropdown. How to fix this and remove the option only for the next select dropdown ?
You can try create two objects of environments and listen selection with valueChanges from formControl. After you get the selected environmentid and filter the other object without this id
Example
ngOnInit(){
this.createForm();
this.getEnvironments();
this.environmentChanges()
}
createForm(){
this.form = this.fb.group({
'environment_id_1': [''],
'environment_id_2' : ['']
})}
getEnvironments(){
const environments = [
{ 'environment_id': 1, 'environment': 'A' },
{ 'environment_id': 2, 'environment': 'B' },
{ 'environment_id': 3, 'environment': 'C' },
{ 'environment_id': 4, 'environment': 'D' }];
this.environments1 = environments;
this.environments2 = environments;}
environmentChanges(){
this.form.controls['environment_id_1'].valueChanges
.subscribe((environment_id)=>{
this.environments2 = this.environments1.filter((env)=> env.environment_id != environment_id)
})}
<form [formGroup]="form">
<div class="row">
<select class="select form-control" formControlName="environment_id_1">
<option value="">Select Environment 1 </option>
<option *ngFor="let environment of environments1" [value]="environment.environment_id"> {{environment.environment}} </option>
</select>
</div>
<div class="row" style="padding-top: 10px;">
<select class="select form-control" formControlName="environment_id_2">
<option value="">Select Environment 2 </option>
<option *ngFor="let environment of environments2" [value]="environment.environment_id"> {{environment.environment}} </option>
</select>
</div>
enter image description here
I have a requirement to build a survey with multiple questions. Based on the response to one of the questions (selected from the drop down) I need to rephrase the next question which also involves drop down selection. I am doing a function call onchange and changing the text of next question and it is getting changes, but the dropdown is not getting displayed. Below is the code snippet. Please let me know what is going wrong.
HTML:
<div class="section" id="question" style="text-align: center;"><!-- Put the questions here - Start -->
<div class="section single-question" id="qs6" onchange="capture()">
<p><span class="number">6.</span>What do you like most about us?</p>
<div class="custom-select"><select id="q6_select" data-storage="experience_call">
<option value="">Please select</option>
<option value="A">ABCD</option>
<option value="E">EFGH</option>
<option value="G">Greatly satisfied by the service</option>
<option value="Others">Others Specify</option>
</select>
<div class="error-message">Please select an item from the menu</div>
</div>
<div class="textarea-container">
<div></div>
<div class="error-message">Please fill out the required field</div>
</div>
</div>
<div class="section single-question" id="qs7">
<p>Why you decided to select:</p>
<div class="custom-select"><select id="q6_select" data-storage="experience_call">
<option value="">Please select</option>
<option value="A">A</option>
<option value="B">B</option>
<option value="Others">Others Specify</option>
</select>
<div class="error-message">Please select an item from the menu</div>
</div>
<div class="textarea-container">
<div></div>
<div class="error-message">Please fill out the required field</div>
</div>
</div>
Script:
function capture() {
var qselect = $("#q6_select").find('option:selected').text();
if(qselect.indexOf("BCD") > 0)
{
$('#qs7').text('You have selected: ABCD');
}
else if(qselect.indexOf("FGH") > 0)
{
$('#qs7').text('You have selected: EFGH');
}
}
I think you have a small error in this line
<div class="section single-question" id="qs7">
You need to close the div and keep it as an empty div, like this:
<div class="section single-question" id="qs7"> </div>
When you are running your JS code, you are replacing all of its contents which includes the next dropdown. See JsFiddle
You can also replace the .text method to use .innerHtml if you want to add some html in that div. Read more here.
I think the above answers your exact question on why the next dropdown is gone. If now you want to also then have some logic to control the next dropdown content, I think this stackoverflow answer will answer it.
Try this:
var Options = {
'A': {
"Please select": "",
"A": "A value",
"B": "B value",
"C": "C value",
"D": "D value",
},
'E': {
"Please select": "",
"E": "E value",
"F": "F value",
"G": "G value",
"H": "H value",
},
'G': {
"Please select": "",
"G": "G value",
},
'Others': {
"Please select": "",
"Others": "Others value",
},
};
$('#q6_select').on('change', function(e) {
if (this.value == "") {
$('#qs7').hide();
$('#error-message-1, #error-message-2').show();
} else {
$('#qs7').text('You have selected: ' + this.options[this.selectedIndex].innerText);
$('#error-message-1, #error-message-2').hide();
$('#error-message-3, #error-message-4').show();
$('#q7_select').empty();
$.each(Options[this.value], function(key, value) {
$('#q7_select').append($("<option></option>").attr("value", value).text(key));
});
}
});
$('#q7_select').on('change', function(e) {
if (this.value == "") {
$('#error-message-3, #error-message-4').show();
} else {
$('#error-message-3, #error-message-4').hide();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="section" id="question" style="text-align: center;"><!-- Put the questions here - Start -->
<div class="section single-question" id="qs6">
<p><span class="number">6.</span>What do you like most about us?</p>
<div class="custom-select"><select id="q6_select" data-storage="experience_call">
<option value="">Please select</option>
<option value="A">ABCD</option>
<option value="E">EFGH</option>
<option value="G">Greatly satisfied by the service</option>
<option value="Others">Others Specify</option>
</select>
<div class="error-message" id="error-message-1">Please select an item from the menu</div>
</div>
<div class="textarea-container">
<div></div>
<div class="error-message" id="error-message-2">Please fill out the required field</div>
</div>
</div>
<div class="section single-question" id="qs7"></div>
<p>Why you decided to select:</p>
<div class="custom-select"><select id="q7_select" data-storage="experience_call">
<option value="">Please select</option>
<option value="A">A</option>
<option value="B">B</option>
<option value="Others">Others Specify</option>
</select>
<div class="error-message" id="error-message-3">Please select an item from the menu</div>
<div class="textarea-container">
<div></div>
<div class="error-message" id="error-message-4">Please fill out the required field</div>
</div>
</div>
Have added an Id pId to the
<p id='pId'>Why you decided to select:</p>
and then in the script added the below code. This worked as per the requirement.
var ptag = docuemnt.getElementById('pId');
ptag.innerhtml = "Your string here";
I have the following dropdown select HTML tags
<label>Car:</label>
<select ng-model="params.CarName">
<option value="x" disabled="" selected="">Select Car...</option>
<option value="BMW">BMW</option>
<option value="Audi">Audi</option>
</select>
<label>Model:</label>
<select ng-if="params.CarName == 'BMW'" ng-model="params.CarModel" ng-change="PerfRpt()">
<option value="x" disabled="" selected="">BMW Sports</option>
<option value="BMW 328i">BMW 328i</option>
<option value="BMW Sports">BMW Sports</option>
</select>
<select ng-if="params.CarName == 'Audi'" ng-model="params.CarModel" ng-change="PerfRpt()">
<option value=" " disabled="" selected="">Audi Sports</option>
<option value="Audi i345">Audi i345</option>
<option value="Audi Sports">Audi Sports</option>
</select>
<select ng-if="params.CarName!= 'BMW' && params.CarName != 'Audi'">
<option>-</option>
</select>
As per the above code, this is wat it does, We have a dropdown to select Car. It is either BMW or Audi.
Depending on this selection, The Model dropdown will be shown. For e.g If we select Audi for Car in the first dropdown, then Audi i345 and Audi Sports will be shown as the dropdown in the 'Model' field.
Similarly, other options will be shown if we select BMW.
Now I am planning to put the Car data in DB along with Model data. Once the page loads, the data will be retrieved and displayed to the user for the 'Car' section. Once the car is selected, depending on the value of the car, its corresponding Model will be updated in the Model section then.
I can get the data from backend to frontend. I want to know how to display those values dynamically and not hardcode like I have done here.
I have the following response from database for the Car.
Results: Array[2]
0: Object
Car:BMW
1: Object
Car:Audi
You need an array with the Car Names, eg.
$scope.carNameOptions = [
'BMW'
'Audi'
];
Then you would do this:
<select ng-model="params.CarName">
<option value="">Select car...</option>
<option ng-repeat="car in carNameOptions" value="{{car}}">{{car}}</option>
</select>
I would suggest making params.CarModel an object with the keys being the CarNames, and the value an array with options for the car like above. Then you can do this:
<select ng-model="params.CarModel">
<option value="">Select model...</option>
<option ng-repeat="carModel in carModelOptions[params.CarName]" value="{{carModel}}">{{carModel}}</option>
</select>
eg
$scope.carModelOptions = {
'BMW' : [
'BMW 328i',
...
],
'Audi' : [...]
}
Since you have only the cars models stored in your database, you can retrieve them and then make a new array putting inside it the types, as follows:
(function() {
"use strict";
angular
.module('app', [])
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope'];
function MainCtrl($scope) {
// From database
var data = [
'BMW',
'Audi'
];
$scope.cars = [
{
"model":"BMW",
"types":[
"BMW 328i",
"BMW Sports"
]
},
{
"model":"Audi",
"types":[
"Audi i345",
"Audi Sports"
]
}
];
}
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body ng-controller="MainCtrl">
<div class="col-md-12">
<select class="form-control" ng-options="car.model for car in cars" ng-model="carSelected">
<option value="" label="Select a car" hidden></option>
</select>
<select class="form-control" ng-disabled="!carSelected" ng-options="type for type in carSelected.types" ng-model="typeSelected">
<option value="" label="Select a type" hidden></option>
</select>
<hr>
Car selected: <pre ng-bind="carSelected | json"></pre>
Type selected: <pre ng-bind="typeSelected"></pre>
</div>
</body>
</html>
Note: I've used ngOptions directive, which one MUST be used for <select>, not ngRepeat.
I hope it helps.
I have some logic written for a form where the available items in the second dropdown change based on the first selection.
The drop downs are cloned to allow the user to work with multiples if needed.
The cloned drop downs change if anything is changed in the original drop down. The second field in the cloned options do not respond to change events in the first.
I would like for each cloned set of fields to behave independantly of the other sets of fields. Here is a fiddle: http://jsfiddle.net/HchH8/
Why is this happening? I tried using clone(true, true) for deep copy and it didn't work. I have searched on SO for similar problems and I just can't wrap my head around the answers I'm finding. I am new to this. Can anyone help me please?
jQuery
prods = {
Cookware: ["- Select -", "Round French Oven", "Oval French Oven", "Braiser", "Skillet", "Fry Pan", "Grill Pan", "Saute Pan", "Saucepan", "Saucier", "Griddle", "Roaster", "Stockpot", "Speciality Cookware", "Other"],
Bakeware: ["- Select -", "Covered Casserole", "Baking Dish", "Stoneware Gratin", "Speciality Bakeware", "Individual Bakeware", "Metal Bakeware", "Other"],
KitchenTools: ["- Select -", "Utensils", "Kitchen Accessories", "Cutlery", "Wine Tools", "Textiles", "Other"],
DineEntertain: ["- Select -", "Dinnerware", "Serveware", "Tabletop Accessories", "Glassware", "Kettles", "Tea Collection", "Café Collection", "Other"]
};
var category = $('select[name^="Product_category"]');
var productType = $('select[name^="Product_type"]');
$('.prod-info').live("change", function () {
var catSelected = $(this).val();
$(this).parent("li").next("li.subCats").fadeIn('fast'); /*Fades in next option once selection has been made*/
if($(this).is(category)) {
$('select[name^="Product_type"]').empty();
$('.product-size, .product-color').prop('selectedIndex',0);
$.each(prods[catSelected], function (key, value) {
$('select[name^="Product_type"]')
.append($("<option></option>")
.attr("value", value)
.attr("name", value)
.text(value));
});
}
if($(this).is(productType)) {
$('.product-size, .product-color').prop('selectedIndex',0);
}
});
var otherSelect = $('select');
var select = this.value;
otherSelect.change(function () {
if ($(this).val() == 'Other') {
$(this).next('.other').show();
}
else $(this).next('.other').hide();
});
for (var i = 2; i < 6; i++) { // add counts in a for loop
$('select[name="numProd"]').append('<option value=' + i + '>' + i + '</option>');
}
$.fn.duplicate = function(count, cloneEvents) {
var tmp = [];
for (var i = 0; i < count; i++) {
$.merge(tmp, this.clone(cloneEvents, true, true).get());
}
return this.pushStack(tmp);
};
//SELECT CHANGE FUNCTION (on change get value and clone)
$('select[name="numProd"]').change(function(){ // on change...
var numOfClones = $(this).val() -1; // get value...
var cntr = 2;
$('#addProds').empty(); // empty holder if there are some old clones
$('.prodDetails').duplicate(numOfClones).appendTo('#addProds').each(function() {
$(this).find("select").each(function() {
if (this.name) {
this.name += cntr;
}
if (this.id) {
this.id += cntr;
}
});
++cntr;
});
// duplicate; fill holder with new clones; the class 'new' is just for styling
});
HTML
<form id="warranty">
<div id="prodDetailsContainer">
<label for="numProd">How many products would you like to register (up to 5) <em>*</em></label>
<select name="numProd">
<option>1</option>
</select>
<ul class="prodDetails" id="prod">
<li>
<label for="Product_category">Product Category <em>*</em></label>
<select name="Product_category" class="category prod-info" style="width: 160px;">
<option value="">- Select Category-</option>
<option value="Cookware">Cookware</option>
<option value="Bakeware">Bakeware</option>
<option value="KitchenTools">Kitchen Tools</option>
<option value="DineEntertain">Dine & Entertain</option>
</select>
</li>
<li style="display: none;" class="subCats">
<label for="Product_type">Product Type <em>*</em></label>
<select name="Product_type" class="product-type prod-info"></select>
<div class="other" style="display: none;">
<label for="Other_Product_Type">Specify Other:: </label>
<input class="text-field" name="Other_Product_Type" />
</div>
</li>
<li style="display: none;" class="subCats">
<label for="Product_size">Product Size <em>*</em></label>
<select name="Product_size" class="product-size prod-info" style="width: auto; outline: none; width:120px;">
<option value="">- Select Size -</option>
<option value="1_QT">1 qt.</option>
<option value="2_QT">2 qt.</option>
<option value="3-half_QT">3 ½ qt.</option>
<option value="4-half_QT">4 ½ qt.</option>
<option value="5_QT">5 qt.</option>
<option value="Other">Other</option>
<option value="NA">Not Applicable</option>
</select>
<div class="other" style="display: none;">
<label for="Other_Product_Size">Specify Other:: </label>
<input class="text-field" name="Other_Product_Size" />
</div>
</li>
<li style="display: none;" class="subCats">
<label for="Product_color">Product Color <em>*</em></label>
<select name="Product_color" class="product-color prod-info">
<option value="">- Select Color -</option>
<option value="Amethyst">Amethyst</option>
<option value="Aubergine">Aubergine</option>
<option value="Black Onyx">Black Onyx</option>
<option value="Caribbean">Caribbean</option>
</select>
</li>
</ul>
<div id="addProds"></div>
</div>
</form>
I figured it out- the solution was to move the variables inside the .on function, and also make the selectors more specific so that only the next fields were affected by a change in the previous (instead of all of them).
$('select').live('change', function() {
var category = $('select[name^="Product_category"]');
var productType = $('select[name^="Product_type"]');
var catSelected = $(this).val();
var nextProdType = $(this).parent("li").next("li.subCats").children('select[name^="Product_type"]');
var nextSizeColor = $(this).parent("li").next("li.subCats").children('.product-size, .product-color');
$(this).parent("li").next("li.subCats").fadeIn('fast'); /*Fades in next option once selection has been made*/
if($(this).is(category)) {
nextProdType.empty();
nextSizeColor.prop('selectedIndex',0);
$.each(prods[catSelected], function (key, value) {
nextProdType
.append($("<option></option>")
.attr("value", value)
.attr("name", value)
.text(value));
});
}
if($(this).is(productType)) {
nextSizeColor.prop('selectedIndex',0);
}
});
Here is a working fiddle in case this will be helpful to others in the future:
http://jsfiddle.net/xJyL7/1/