Select component - use selects (dropdown) to display multiple other components?

Hi forum,

How to get an option selected in a select, to show a hidden select (2nd select) and then have the option of that 2nd select then reveal a hidden div?

Example:

Basically, the 2nd select is initially hidden, only revealed if the user select’s ‘Yes’ in the first select.

Then, depending on which option the user select in the 2nd (now revealed) select, will open up a specific DIV containing additional components. Example, if Audio is selected, then the Audio DIV is displayed. If Video is selected, only the Video DIV is displayed.

If the user goes back to the first Select and chooses ‘No’, the DIV and the 2nd Select go back to hidden.

Would a Collapse work here for the DIV area? I could delete the default button, but then how to get it to open up the respective DIV depending on what was selected in Select 2?

Thank you.

Javascript:

document.addEventListener('DOMContentLoaded', function() {
    const addFilesSelect = document.getElementById('addFiles');
    const fileTypeContainer = document.getElementById('fileTypeContainer');
    const fileTypeSelect = document.getElementById('fileType');
    const fileInputContainer = document.getElementById('fileInputContainer');

    addFilesSelect.addEventListener('change', function() {
        if (this.value === 'yes') {
            fileTypeContainer.style.display = 'block';
        } else {
            fileTypeContainer.style.display = 'none';
            fileInputContainer.innerHTML = ''; // Clear file input
        }
    });

    fileTypeSelect.addEventListener('change', function() {
        let fileInputHtml;
        switch (this.value) {
            case 'image':
                fileInputHtml = '<h4>Add Image Files</h4><input type="file" accept="image/*" name="fileInput" id="fileInput" class="dragndrop">';
                break;
            case 'audio':
                fileInputHtml = '<h4>Add Audio Files</h4><input type="file" accept="audio/*" name="fileInput" id="fileInput" class="dragndrop">';
                break;
            case 'video':
                fileInputHtml = '<h4>Add Video Files</h4><input type="file" accept="video/*" name="fileInput" id="fileInput" class="dragndrop">';
                break;
            default:
                fileInputHtml = '';
        }
        fileInputContainer.innerHTML = fileInputHtml;
        fileInputContainer.style.display = 'block';
    });
});

Optional CSS for the drag and drop:

.dragndrop {
  height: 100%;
  width: 100%;
  min-height: 200px;
  border: 3px dashed var(--bs-gray-500);
  position: relative;
}

.dragndrop::after {
  position: absolute;
  content: "Or Drag and Drop";
  top: 50%;
  left: 0;
  right: 0;
  text-align: center;
}```

I don’t understand the point of the approach to show a input field by show a second select component and depend of the value of the second select show an input field type file. You can have an input type file that accept the allowed files like this

<div class="input-group">
	<span class="input-group-text">Add more files</span>
	<input class="form-control" 
		type="file" 
		multiple 
		accept="audio/*,video/*,image/*,.txt"
	>
</div>

Thank you for the reply and suggestion here. I’ll give it a go!

By the way, how are you guys putting those examples on the bss.design site?

And the only way to look at the code behind it is to use browser dev tools, right?

Also, is there a Bootstrap Studio key shortcut to find matching brackets in Javascript code?

I was recently reading an article on PHP and file types and had that on the brain when I asked this question. I should have used something like…maybe descriptions for vehicles like:

1st select - Add more info about vehicles?
2nd select - Which type: Car, Truck, Motorcycle
3rd, Respective DIV opens up with typical form objects (text, checkboxes, etc.) to add more information about each category.

Sorry for the bad example and thanks for the reply!

Upon selecting Yes, the next select does show, however…the label (span) takes up the entire col and the select is wrapped below it:

Right now, I’m working in the XXL mode, so both columns are col-xxl-6.
The ID is on the Input Group.

Is there something in fileTypeContainer.style that can make sure the Input Group span and select stay together like this:

I found that “fileTypeContainer.style.display = ‘flex’;” seems to work (both in BSS designer and viewing on the preview web page).

Are there any drawbacks or concerns with setting style.display with “flex” since “block” doesn’t maintain the design?

You can wrap the label and select input in a div with a class of ‘input-group’

Looking something like this:

<div class="col-md-6">
    <div class="input-group"><label class="input-group-text" for="addFiles">Add more files?</label><select id="addFiles" class="form-select" name="addFiles">
            <option value selected>Do you want to add files?</option>
            <option value="no">No</option>
            <option value="yes">Yes</option>
        </select></div>
</div>

For some reason bootstrap studio doesn’t allow you to remove the ‘form-label’ class from the label so you need to convert it to custom code to edit it. @martin can this be given the option to remove in the next update?

I have updated the example I posted earlier.

Click on the down arrow next to publish in the top right corner of the screen:
Select Publish Settings
image

Then click on manage websites
image

Bootstrap Studio Sites Tab

then click ‘Add website’

You can find more info here: Publishing Your Website Online | Bootstrap Studio

@richards

You can use the input-group and label the select like this

<div class="input-group">
	<span class="input-group-text" id="labelForAddFiles">Add more files?</span>
	<select class="form-select" id="addFiles" aria-labelledby="labelForAddFiles">
		<option value="0" selected>No</option>
		<option value="1">Yes</option>
	</select>
</div>

then you don’t need to have it as custom-code block

2 Likes

I’m trying to populate a select with data from a .json file, and getting an error (as seen in browser dev counsel):

GET http://[my.local.i.p.]:8000/auto_data.json 404 (Not Found)

The .json file is located, for now in localhost, in the same directory level as the webpage & javascript calling it.

The JS:

    let autoYearsSelect = document.querySelector("auto_years-1"); //Carousel with more than 1 slide.

    //AJAX request - Get the list of States and Years
    fetch ("auto_data.json")
    .then (function(response) {
        return response.json();
    })
        
    .then (function(data) {
      let years = data [autos];
      let out = "";
      out += '<option value="">Choose a Year</option>'; 
      for (let year of years) {
        out += '<option value="${year}">${year}</option>'; 
      } 
    
      autoYearsSelect .innerHTML = out;

A snippet of what the json file holds:

{
“BMW”: [“1980”,“1981”,“1982”,“1983”],
“Chevy”: [“1970”,“1978”,“1979”,“1981”,“1985”,“1987”,“1990-95”],
“Honda”: [“1966”,“1967”,“1969”,“1972”,“1974”,“1976”,“1980”,“1982”],
}

There are two select dropdowns. For example:
Cars - which has options: “-Select A Car Brand-”, “BMW”, “Chevy”, “Honda”
Years - which is initially empty but should be populated with the years data based on the json file.

So, for example, if the user selects “BMW” in the 1st select, then the 2nd existing select (w/no options initially) next to it should get populated with options “1980”,“1981”,“1982”,“1983”.

If the user subsequently chooses “Chevy”, then those years should be the only options in the 2nd, or Years, select dropdown.

If the user goes back to the first select Cars and choose the default -Select A Car Brand-, the Years select should be emptied of options but still on the form.

Thoughts on why the 404 error?

You can do it like this without a json-file

<form>
	<div class="row">
		<div class="col">
			<div class="input-group">
				<span class="input-group-text">Brand</span>
				<select class="form-select" id="brand" name="brand" aria-label="Car brand">
					<option value="" selected="">-Select A Car Brand-</option>
					<option value="BMW">BMW</option>
					<option value="Chevy">Chevy</option>
					<option value="Honda">Honda</option>
				</select>
			</div>
		</div>
		<div class="col">
			<div class="input-group">
				<span class="input-group-text">Year</span>
				<select class="form-select" id="year" aria-label="Year of the car"></select>
			</div>
		</div>
	</div>
</form>
const autos = {
  BMW: ['1980', '1981', '1982', '1983'],
  Chevy: ['1970', '1978', '1979', '1981', '1985', '1987', '1990-95'],
  Honda: ['1966', '1967', '1969', '1972', '1974', '1976', '1980', '1982'],
};

const selectBrand = document.getElementById('brand');
const selectYear = document.getElementById('year');
selectBrand.addEventListener('change', () => {
  selectYear.innerHTML = '';
  const selYear = document.createElement('option');
  selYear.text = '-Select A Year-';
  selYear.value = '';
  selectYear.append(selYear);
  const years = autos[selectBrand.value];
  if (years) {
    for (let i = 0; i < years.length; i++) {
      const option = document.createElement('option');
      option.value = years[i];
      option.text = years[i];
      selectYear.append(option);
    }
  }
});

Your json files in BSS lives in the assets/js folder so you fetch the json
like this
fetch ("assets/js/auto_data.json")

1 Like

Your json files in BSS lives in the assets/js folder so you fetch the json
like this
fetch ("assets/js/auto_data.json")

Ah, ok…no wonder.

And, instead of relying on an (additional) outside file like .json, seems better to keep it within the js file.

Thank you!

Here is an example fetching from a json file with a simple formSubmitHandler

Thats awesome! Thanks for the great demo. :beers: