У меня есть файл JSON, в котором много данных, таких как:
[ {
"manufacturer": "Samsung",
"gadget": "Smart Phone",
"model": "Note 9"
},
{
"manufacturer": "Apple",
"gadget": "Smart Phone",
"model": "iPhone 5"
},
...]
Мне нужно получить эти данные с помощью javascript, а затем отправить их в тег select в файле HTML.
Вот как выглядит мой HTML, я бы также включил js, но я понятия не имею, как запустить или инициализировать JSON и отправить его в HTML...
<main>
<section id = "welcome-section-shop">
<div id = "welcome-header">
<h2>Web shop</h2>
</div>
</section>
<section class = "shop-section">
<div id = "shop-header">
<div id = "shop-div">
<h1>Step 1: Select manufacturer</h1>
<hr id = "shop-hr">
<select class = "select-option" id = "select" name = "select">
<option value = "">Select manufacturer</option>
</select>
<h1>Step 2: Select gadget type</h1>
<hr id = "shop-hr">
<select class = "select-option" id = "select" name = "select">
<option value = "">Select gadget</option>
</select>
<h1>Step 3: Select model</h1>
<hr id = "shop-hr">
<select class = "select-option" id = "select" name = "select">
<option value = "">Select model</option>
</select>
</div>
</div>
</section>
</main>



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Для вашего кода
<section id = "welcome-section-shop">
<div id = "welcome-header">
<h2>Web shop</h2>
</div>
</section>
<section class = "shop-section">
<div id = "shop-header">
<div id = "shop-div">
<h1>Step 1: Select manufacturer</h1><hr id = "shop-hr">
<select class = "select-option" id = "select1" name = "select">
<option value = "">Select manufacturer</option>
</select>
<h1>Step 2: Select gadget type</h1><hr id = "shop-hr">
<select class = "select-option" id = "select2" name = "select">
<option value = "">Select gadget</option>
</select>
<h1>Step 3: Select model</h1><hr id = "shop-hr">
<select class = "select-option" id = "select3" name = "select">
<option value = "">Select model</option>
</select>
</div>
</div>
</section>
<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var data = xhttp.responseJSON;
for(var i in data){
var option1 = document.createElement('option');
var option2 = document.createElement('option');
var option3 = document.createElement('option');
option1.text = data[i]["manufacturer"];
option2.text = data[i]["gadget"];
option3.text = data[i]["model"];
document.getElementById('select1').appendChild(option1);
document.getElementById('select2').appendChild(option2);
document.getElementById('select3').appendChild(option3);
}
}
};
xhttp.open("GET", "filename", true);
xhttp.send();
</script>
Вы можете использовать объект XMLHttpRequest для отправки запроса AJAX, и после того, как вы получите данные с сервера, вы можете добавить параметры к элементу выбора, используя итерацию данных JSON.
HTML
<select id = "abc">
</select>
JS
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var data = xhttp.responseJSON;
for(var i in data){
var op = document.createElement('option');
op.text=data[i].text;
op.value=data[i].value;
document.getElementById('abc').appendChild(op);
}
}
};
xhttp.open("GET", "filename", true);
xhttp.send();
где ваши данные будут как [{"text":"abc","value":"abc"},{.......]
Используйте получить API для загрузки файла json.
const handleAsJson = response => response.json();
const handleError = console.error // or some such;
fetch('/url/to/file.json')
.then(handleAsJson)
.catch(handleError);
Я рекомендую использовать легкую библиотеку шаблонов под названием горит-html для построения вашего DOM.
<section id = "welcome-section-shop">
<div id = "welcome-header">
<h2>Web shop</h2>
</div>
</section>
<section class = "shop-section">
<div id = "shop-header">
<div id = "shop-div">
<h1>Step 1: Select manufacturer</h1><hr id = "shop-hr">
<select class = "select-option" id = "manufacturer-select" name = "select">
<option value = "">Select manufacturer</option>
</select>
<h1>Step 2: Select gadget type</h1><hr id = "shop-hr">
<select class = "select-option" id = "gadget-select" name = "select">
<option value = "">Select gadget</option>
</select>
<h1>Step 3: Select model</h1><hr id = "shop-hr">
<select class = "select-option" id = "model-select" name = "select">
<option value = "">Select model</option>
</select>
</div>
</div>
</section>
<script type = "module">
import { render, html } from 'https://unpkg.com/lit-html/lit-html.js?module';
const manufacturerSelect = document.getElementById('manufacturer-select')
const modelSelect = document.getElementById('model-select')
const gadgetSelect = document.getElementById('gadget-select')
// converts array of items into more manageable object
const traverse = items => items.reduce((acc, { gadget, manufacturer, model }) => ({
gadgets: [...acc.gadgets, gadget],
manufacturers: [...acc.manufacturer, gadget],
models: [...acc.models, gadget],
}), {})
// defines the template for an option element with interpolated string attribute and content
const optionTpl = string => html`<option value = "${string}">${string}</option>`;
// renders all option values to each select element
const renderTemplates = ({ gadget, manufacturer, model }) => {
render(html`<option value = "">Select manufacturer</option>${manufacturer.map(optionTpl)}`, manufacturerSelect)
render(html`<option value = "">Select model</option>${model.map(optionTpl)}`, modelSelect)
render(html`<option value = "">Select gadget</option>${gadget.map(optionTpl)}`, gadgetSelect)
}
const handleAsJson = response => response.json();
const handleError = console.error // or some such;
fetch('/url/to/file.json')
.then(handleAsJson)
.then(traverse)
.then(renderTemplates)
.catch(handleError);
</script>
Вы также можете рассмотреть возможность определения пользовательского элемента для раскрывающихся списков, который будет принимать атрибут-заполнитель для определения этой строки, а также массив строковых параметров в качестве свойства. Однако имейте в виду, что на данный момент вам нужно будет получить доступ к значению выбора с помощью javascript, поскольку API участия в формах еще не готов.
<section id = "welcome-section-shop">
<div id = "welcome-header">
<h2>Web shop</h2>
</div>
</section>
<section class = "shop-section">
<div id = "shop-header">
<div id = "shop-div"></div>
</div>
</section>
<script type = "module">
import { render } from 'https://unpkg.com/lit-html/lit-html.js?module';
import { LitElement, html, css } from 'https://unpkg.com/lit-element/lit-element.js?module';
const traverse = items => items.reduce(({gadgets = [], manufacturers = [], models = []}, { gadget, manufacturer, model }) => ({
gadgets: [...gadgets, gadget],
manufacturers: [...manufacturer, manufacturer],
models: [...models, model],
}), {})
const optionTpl = string => html`<option value = "${string}">${string}</option>`;
customElements.define('shop-dropdown', class extends LitElement {
static get properties() {
return {
placeholder: { type: String },
items: { type: Array },
};
}
static get styles() {
return css`
:host {
display: block;
}
select {
/*...*/
}
`
}
get value() {
return (
this.shadowRoot &&
this.shadowRoot.querySelector('select') &&
this.shadowRoot.querySelector('select').value
);
}
render() {
return html`
<select>
<option>${this.placeholder}</option>
${this.items.map(optionTpl)}
</select>
`
}
});
const handleAsJson = response => response.json();
const handleError = console.error // or some such;
const renderTemplates = ({ gadgets, models, manufacturers }) => render(html`
<h1>Step 1: Select manufacturer</h1>
<hr/>
<shop-select placeholder = "Select manufacturer" .items=${manufacturers}></shop-select>
<h1>Step 2: Select gadget type</h1>
<hr/>
<shop-select placeholder = "Select gadget" .items=${gadgets}></shop-select>
<h1>Step 3: Select model</h1>
<hr/>
<shop-select placeholder = "Select model" .items=${models}></shop-select>
`, document.getElementById('shop-div'))
fetch('/url/to/file.json')
.then(handleAsJson)
.then(traverse)
.then(renderTemplates)
.catch(handleError);
</script>
HTML:
<h1>Step 1: Select manufacturer</h1><hr id = "shop-hr">
<select class = "select-option" id = "select-manufacturer" name = "manufacturer">
<option id = "manufacturer-placeholder" value = "">Select manufacturer</option>
</select>
<h1>Step 2: Select gadget type</h1><hr id = "shop-hr">
<select class = "select-option" id = "select-gadget" name = "gadget" disabled>
<option id = "gadget-placeholder" value = "">Select gadget</option>
</select>
<h1>Step 3: Select model</h1><hr id = "shop-hr">
<select class = "select-option" id = "select-model" name = "model" disabled>
<option id = "model-placeholder" value = "">Select model</option>
</select>
Отформатируйте данные следующим образом:
{
"Samsung": {
"Smart Phone": [ "Note 9", ],
// ...
},
"Apple": {
"Smart Phone: [ "iPhone 5", /* ... */ ],
// ...
},
// ...
}
Скрипт
const xhr = new XMLHttpRequest()
const url = 'path/to/file.json'
xhr.onreadystatechange = function() {
if ((this.readyState == 4) && (this.status == 200)) {
const array = JSON.parse(this.responseText)
const formatted = formatData(array)
start(formatted)
}
}
function formatData(array) {
const res = {}
for (let item of array) {
const gadgets = res[item.manufacturer] || (res[item.manufacturer] = {})
const models = gadgets[item.gadget] || (gadgets[item.gadget] = [])
models.push(item.model)
}
return res
}
function start(data) {
const selectManufacturer = document.getElementById('select-manufacturer')
const selectGadget = document.getElementById('select-gadget')
const selectModel = document.getElementById('select-model')
for (let manufacturer in data) {
selectManufacturer.appendChild(createOption(manufacturer))
}
let gadgets
selectManufacturer.addEventListener('change', () => {
gadgets = data[selectManufacturer.value]
selectGadget.innerHTML = ''
selectGadget.appendChild(placeholderOption('gadget'))
for (let gadget in gadgets) {
selectGadget.appendChild(createOption(gadget))
}
selectGadget.disabled = false
selectModel.innerHTML = ''
selectModel.appendChild(placeholderOption('model'))
selectModel.disabled = true
const placeholder = document.getElementById('manufacturer-placeholder')
if (placeholder) selectManufacturer.removeChild(placeholder)
})
selectGadget.addEventListener('change', () => {
const models = gadgets[selectGadget.value]
selectModel.innerHTML = ''
selectModel.appendChild(placeholderOption('model'))
for (let model of models) {
selectModel.appendChild(createOption(model))
}
selectModel.disabled = false
const placeholder = document.getElementById('gadget-placeholder')
if (placeholder) selectGadget.removeChild(placeholder)
})
selectModel.addEventListener('change', () => {
const placeholder = document.getElementById('gadget-placeholder')
if (placeholder) selectModel.removeChild(placeholder)
})
}
function createOption(value, text) {
if (text == undefined) text = value
let opt = document.createElement('option')
opt.value = value
opt.innerHTML = text
return opt
}
function placeholderOption(type) {
let opt = createOption('', `Select ${type}`)
opt.id = `${type}-placeholder`
return opt
}
возможно вот так? { "Samsung": { "Смартфон": [ "Note 9", "Galaxy S8"], "Планшет": ["abc", "abc"], "Smart Watch": ["abc", "abc" ] }, "Apple": { "Смартфон": [ "Note 9", "Galaxy S8"], "Планшет":[], "Smart Watch": ["abc", "abc"] }, "Huawei ": { "Смартфон": [ "Note 9", "Galaxy S8"], "Планшет": ["abc", "abc"], "Smart Watch": ["abc", "abc"] } }
Это самый простой способ сделать надежный выпадающий список. Функция formatData() отформатирует ваши данные таким образом, если они будут такими, как вы представили их в вопросе...
Если ваш JSON организован таким образом, пропустите функцию formatData().
В любом случае это не работает, но ваш код выглядит более чем нормально :(
обработчик readystatechange: const data = JSON.parse(this.responseText); start(data)
Эй быстрый вопрос! В JSON у меня есть следующие данные: 3 производителя, Samsung, Apple и Huawei, 3 разных типа гаджетов, смартфон, планшет, умные часы и 5+ разных моделей каждого типа гаджета. В этом случае, как мне организовать JSON?