Answer the question
In order to leave comments, you need to log in
What algorithm of actions is better? How to send a POST request using the request module? How to save an array of data on the server and update it once a day?
How to do the right thing?
The task is to get a list of company cities from a third-party API (NovaPoshtaAPI), based on the data received, I want to make a calculator with drop-down lists - a choice of cities.
A bit about the API
1) The API uses POST requests from the client
2) Cities are unloaded by the entire directory, there is no way to pull out cities one at a time.
Approach 1 (via AJAX request on client without server)
let cityObj = {
"modelName": "Address",
"calledMethod": "getCities",
"methodProperties": {},
"apiKey": apiKey
};
let xhr = new XMLHttpRequest();
xhr.open('POST', 'https://api.novaposhta.ua/v2.0/json/');
xhr.setRequestHeader('Content-type', 'application/json; charset = utf-8');
//Отправка данных на сервер
xhr.send(JSON.stringify(cityObj));
//проверяем состояние запроса
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState < 4) {
} else if (xhr.readyState === 4 && xhr.status === 200) {
let city = [];
let obj = {};
let cities = JSON.parse(xhr.response);
for (let i = 0; i < cities.data.length; i++) {
obj = {
Ref: cities.data[i].Ref,
Description: cities.data[i].Description
};
//Сформировали справочник населенных пунктов
city.push(obj);
}
console.log(city); //получаем массив из 4000+ населенных пунктов
//Далее вся логика(живой поиск, формирование выпадающего списка, другие действия)
} else {
console.log('Что то пошло не так');
}
});
app.get('/city', function(req,res){
if (!req.body) return res.sendStatus(400);
let cityObj = {
"modelName": "Address",
"calledMethod": "getCities",
"methodProperties": {},
"apiKey": 'apiKey'
};
request.post('https://api.novaposhta.ua/v2.0/json/', {form: cityObj}, function (error, response, body) {
let data = body; //массив с городами
res.send(data);
});
});
let cargoType = calcForm.elements['cargo-type'];
const cargoTypeObj = {
"modelName": "Common",
"calledMethod": "getCargoTypes",
"methodProperties": {},
"apiKey": apiKey
};
sendAjax(cargoType, cargoTypeObj);
function sendAjax(elem, reqObj) {
let xhr = new XMLHttpRequest();
xhr.open('POST', 'https://api.novaposhta.ua/v2.0/json/');
xhr.setRequestHeader('Content-type', 'application/json; charset = utf-8');
//Отправка данных на сервер
xhr.send(JSON.stringify(reqObj));
//проверяем состояние запроса
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState < 4) {
} else if (xhr.readyState === 4 && xhr.status === 200) {
let type = JSON.parse(xhr.response);
for(let i = 0; i < type.data.length; i++) {
createOptions(type.data[i]);
elem.append(createOptions(type.data[i]));
}
//Формируем данные в декоративном селекте
if(cargoType.previousElementSibling.hasAttribute('data-select')){
let select = elem.previousElementSibling.querySelector('.form-select__dropdown');
for(let i = 0; i < type.data.length; i++) {
createSelectItem(type.data[i]);
select.append(createSelectItem(type.data[i]));
}
}
} else {
console.log('Что то пошло не так');
}
});
}
//Создаем пункты реального селекта ++
function createOptions(data){
//Формируем реальный селект
let opt = document.createElement('option');
opt.value = data.Ref;
opt.textContent = data.Description;
return opt;
}
//Создаем пункты декоративного селекта ++
function createSelectItem(data) {
let selectItem = document.createElement('div');
selectItem.classList.add('form-select__item');
selectItem.setAttribute('data-select-item', data.Ref);
selectItem.textContent = data.Description;
return selectItem;
}
Answer the question
In order to leave comments, you need to log in
Kovalsky , based on the described algorithm of actions, the following turned out
Option 1 (search for cities is carried out on the server with the return of the result to the client)
Server part (express js + nodejs)
//используем этот запрос для живого поиска
app.post('/city', function(req,res){
let text = req.body.text;
let val = text.trim().toLowerCase(); // приходит от пользователя
console.log(val);
let city = arr.filter(el => {
if(val){
return el.Description.toLowerCase().search(val) !== -1;
}
});
res.send(city); // возвращаем массив с данными иначе пустой массив
});
app.listen(PORT, function(){
console.log(`Прослушиваем порт по адресу ${PORT}`);
//Формируем справочник городов компании
let cityObj = {
"modelName": "Address",
"calledMethod": "getCities",
"methodProperties": {},
"apiKey": apiKey
};
request.post(
'https://api.novaposhta.ua/v2.0/json/',
{
json: cityObj,
headers: {
"Content-type": "application/json",
}
},
function (error, response, body) {
let data = body;
for(let i = 0; i < data.data.length; i++) {
arr.push(data.data[i]);
console.log(arr[i]);
}
});
});
let city = calcForm.elements['cargo-city-to'];
if(city.previousElementSibling.hasAttribute('data-select')){
let el = city.previousElementSibling.querySelector('[data-select-title]');
el.setAttribute('contenteditable', true);
el.addEventListener('focus', function(){
this.textContent = '';
});
el.addEventListener('input', function(){
//Очистка декоративных пунктов
let selected = city.previousElementSibling.querySelectorAll('[data-select-item]');
selected.forEach(el => {
console.log(el.textContent);
el.remove();
});
//очистка стандартного селекта
for(let i = 0; i < city.options.length; i++){
city.remove(i);
}
//Запрос живого поиска
let xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:3010/city');
xhr.setRequestHeader('Content-type', 'application/json; charset = utf-8');
//Отправка данных на сервер
xhr.send(JSON.stringify({text: this.textContent}));
console.log(this.textContent);
//проверяем состояние запроса
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState < 4) {
} else if (xhr.readyState === 4 && xhr.status === 200) {
let data = JSON.parse(xhr.response);
for(let i = 0; i < data.length; i++) {
//Формируем список опций у реального селекта
createOptions(data[i]);
city.append(createOptions(data[i]));
}
//Формируем данные в декоративном селекте
if(city.previousElementSibling.hasAttribute('data-select')){
let select = city.previousElementSibling.querySelector('.form-select__dropdown');
for(let i = 0; i < data.length; i++) {
createSelectItem(data[i]);
select.append(createSelectItem(data[i]));
}
}
} else {
console.log('Что то пошло не так');
}
});
});
}else{
console.log('---');
}
getCity(city, `http://localhost:3010/city`);
//Изначально загружаем с сервера 5 записей из массива городов (что бы декоративный селект имел некоторый список по умолчанию)
function getCity(elem, url){
let xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.setRequestHeader('Content-type', 'application/json; charset = utf-8');
//Отправка данных на сервер
xhr.send();
//проверяем состояние запроса
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState < 4) {
} else if (xhr.readyState === 4 && xhr.status === 200) {
let data = JSON.parse(xhr.response);
for(let i = 0; i < 5; i++) {
createOptions(data[i]);
elem.append(createOptions(data[i]));
}
//Формируем данные в декоративном селекте
if(elem.previousElementSibling.hasAttribute('data-select')){
let select = elem.previousElementSibling.querySelector('.form-select__dropdown');
for(let i = 0; i < 5; i++) {
createSelectItem(data[i]);
select.append(createSelectItem(data[i]));
}
}
} else {
console.log('Что то пошло не так');
}
});
}
//Получение городов компании
let cityTo = calcForm.elements['cargo-city-to'];
let cityFrom = calcForm.elements['cargo-city'];
checkKeyCity('Mycity', cityTo);
checkKeyCity('Mycity', cityFrom);
//Получение куки
function getCookie(name) {
let matches = document.cookie.match(new RegExp(
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
));
return matches ? decodeURIComponent(matches[1]) : undefined;
}
//Загрузка городов в localStorage
function getCities(){
let date = new Date();
date = new Date(date.setDate(date.getDate() + 1));
let cityObj = {
"modelName": "Address",
"calledMethod": "getCities",
"methodProperties": {},
"apiKey": apiKey
};
let xhr = new XMLHttpRequest();
xhr.open('POST', 'https://api.novaposhta.ua/v2.0/json/');
xhr.setRequestHeader('Content-type', 'application/json; charset = utf-8');
//Отправка данных на сервер
xhr.send(JSON.stringify(cityObj));
//проверяем состояние запроса
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState < 4) {
} else if (xhr.readyState === 4 && xhr.status === 200) {
let city = [];
let obj = {};
let cities = JSON.parse(xhr.response);
for (let i = 0; i < cities.data.length; i++) {
obj = {
Ref: cities.data[i].Ref,
Description: cities.data[i].Description
};
//Сформировали справочник населенных пунктов
city.push(obj);
}
localStorage.setItem('Mycity', JSON.stringify(city));
} else {
console.log('Что то пошло не так');
}
});
document.cookie = `${decodeURI('cities')} = ${decodeURI(true)}; expires = ${date}; path = /`;
}
//Проверка наличие куки
if(getCookie('cities') === undefined) {
getCities();
}
//Проверка наличия ключа в localStorage
function checkKeyCity(key, element){
if (localStorage.getItem(key) !== null){
let data = JSON.parse(localStorage.getItem(key));
//Формируем данные в селекте
for(let i = 0; i < data.length; i++) {
createOptions(data[i]);
element.append(createOptions(data[i]));
}
//Формируем данные в декоративном селекте
if(element.previousElementSibling.hasAttribute('data-select')){
let select = element.previousElementSibling.querySelector('.form-select__dropdown');
select.overflowY = 'scroll';
for(let i = 0; i < data.length; i++) {
createSelectItem(data[i]);
select.append(createSelectItem(data[i]));
}
}
let el = element.previousElementSibling.querySelector('[data-select-title]');
el.setAttribute('contenteditable', true);
el.addEventListener('focus', function(){
this.textContent = '';
});
//Живой поиск ++
el.addEventListener('input', function(){
element.previousElementSibling.querySelector('.form-select__dropdown').classList.remove('hidden');
let val = this.textContent.trim().toLowerCase();
let items = element.previousElementSibling.querySelectorAll('.form-select__item');
if(val != ''){
items.forEach(function(elem) {
if(elem.textContent.toLowerCase().search(val) == -1) {
elem.classList.add('hidden');
}else{
elem.classList.remove('hidden');
}
});
}else{
items.forEach(function(elem) {
elem.classList.remove('hidden');
});
}
});
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question