Асинхронное получение данных из textInput

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Асинхронное получение данных из textInput

Сообщение andrej3337 »

Здравствуйте.
Есть форма. Базы данных не используются.

Можно ли в yii2 как то асинхронно получать вводимые в textInput значения? По аналогии с php, когда прописываешь функцию к полю с id='name' ('#name') или class='name' ('.name')? Как указать скрипту textInput из которого брать вводимые данные?

Цель - при введении в поле наименования организации, отправлять запрос в егр, получая данные по api, соответственно живым поиском асинхронно при вводе каждого символа. Может есть у кого подобные наработки или готовые решения, поделитесь пожалуйста.

Спасибо.
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Асинхронное получение данных из textInput

Сообщение unknownby »

andrej3337 писал(а): 2020.09.10, 14:10 Здравствуйте.
Есть форма. Базы данных не используются.

Можно ли в yii2 как то асинхронно получать вводимые в textInput значения? По аналогии с php, когда прописываешь функцию к полю с id='name' ('#name') или class='name' ('.name')? Как указать скрипту textInput из которого брать вводимые данные?

Цель - при введении в поле наименования организации, отправлять запрос в егр, получая данные по api, соответственно живым поиском асинхронно при вводе каждого символа. Может есть у кого подобные наработки или готовые решения, поделитесь пожалуйста.

Спасибо.
Ввел в текстовое поле что нужно, нажимаем кнопку и при помощи ajax отправляем данные на контроллер, который обращается к api и возвращает информацию, которую получили по api. Далее эту информацию отображаем в нужном месте. Можно сразу отправлять запрос на api.

Если нужно при вводе, сразу отправлять что-то, можно использовать .on('change')
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Re: Асинхронное получение данных из textInput

Сообщение andrej3337 »

unknownby писал(а): 2020.09.10, 14:14 Ввел в текстовое поле что нужно, нажимаем кнопку и при помощи ajax отправляем данные на контроллер, который обращается к api и возвращает информацию, которую получили по api. Далее эту информацию отображаем в нужном месте. Можно сразу отправлять запрос на api.

Если нужно при вводе, сразу отправлять что-то, можно использовать .on('change')
Через нажатие на кнопку средствами yii я реализовал.
Интересует живой поиск при введении символов в поле, а как обратиться к соответствующему textInput? Если ему присвоить id='name', то через ('#name') ничего не происходит.
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Асинхронное получение данных из textInput

Сообщение unknownby »

andrej3337 писал(а): 2020.09.10, 15:01 Через нажатие на кнопку средствами yii я реализовал.
Интересует живой поиск при введении символов в поле, а как обратиться к соответствующему textInput? Если ему присвоить id='name', то через ('#name') ничего не происходит.
Смотри через console.log, работает или нет твой JS.
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Асинхронное получение данных из textInput

Сообщение unknownby »

andrej3337 писал(а): 2020.09.10, 15:01 Через нажатие на кнопку средствами yii я реализовал.
Интересует живой поиск при введении символов в поле, а как обратиться к соответствующему textInput? Если ему присвоить id='name', то через ('#name') ничего не происходит.
Добавь, где у тебя находится поле и пробуй.

Код: Выделить всё

$js = <<<JS
    $('#name').on('input', function(){
        var data = $(this).val();
        if(data.length > 2){
            console.log(1);
        } else {
            console.log(2);
        }
        return false;
    });
JS;

$this->registerJs($js);
Как только получится увидеть лог, приступай ко второму шагу. Отправка данных по api.

Код: Выделить всё

	if(data.length > 2){
            $.ajax({
                url: 'someUrl',
                type: 'POST',
                data: {search:data}, //формируешь данные, которые пойдут на API
                success: function(result) {
                    $(".blockSearch").html(result); //результат будет возвращен в блок, результат страница какая-то, может другой в зависимости от того, что возвращает API
                }
            });
        } else {
            $(".blockSearch").empty(); //тут очистка результата, если стираем в инпуте и количество символов меньше двух
        }
На сколько хватает фантазии, на столько и реализуем данный сервис ;)
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Re: Асинхронное получение данных из textInput

Сообщение andrej3337 »

Спасибо, вечером попробую. Способ который нашел в сети относился к первому шагу, отрабатывал без ошибок в консоли, но данные какие-то приходили в виде кода страницы после каждого ввода символа в поле. Хорошо, буду пробовать :)
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Асинхронное получение данных из textInput

Сообщение unknownby »

andrej3337 писал(а): 2020.09.11, 10:25 Спасибо, вечером попробую.
Первая вещь это просто проверить, работает ли нажатие внутри твоего инпута, если срабатывает, то в консоли будут прописываться единицы и двойки, дальше вместо вывода в консоль уже меняешь как на втором куске кода.
На всякий случай поясню еще разок :)
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Re: Асинхронное получение данных из textInput

Сообщение andrej3337 »

Игрался долго, получилось дергать как и задумывалось, получаю данные в инпут, после чего он нормально внутренними функциями yii2 валидируется и получается в пост. Через for получаю список наименований организаций в зависимости от введенных символов, правда выводится из списка последний. Но тут надо почитать по методам как вывести выпадающий список с ограничением по количеству отображаемых элементов и выбором нужного. Вроде технически понятно куда копать и что искать.

Но есть одно НО. Если дергать с этого адреса методом GET http://egr.gov.by/v2/egr/getShortInfoBy ... йматериалы, а к нему без всяких ? подставляется после слеша вводимый текст, то браузеры ругаются на ...CORS policy: No 'Access-Control-Allow-Origin' header... как будто сервер egr.gov.by не настроен на отдачу любому кто обратиться.

Но при этом есть сервисы, которые как-то дергают данные оттуда, других источников нету, например https://legat.by/. Блин, на работе хром не показывает в коносли ничего, в firefox консоль показывает, что отправляется post запрос на какой-то внутренний адрес. Т.е. может быть что для обхода ограничений нужно сначала принять данные где-то в контролере методом GET с http://egr.gov.by/v2/egr/getShortInfoByRegName/, а потом уже полученные данные дергать из него себе в форму методом POST?
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Асинхронное получение данных из textInput

Сообщение unknownby »

andrej3337 писал(а): 2020.09.14, 10:21 Но есть одно НО.
Если у них нет явного API по работе с их данными (которого скорее всего нет), которые уже явно кто-то забирает у них. Значит у них есть вариант забора данных через передачу всего набора данных. Что подразумевает под собой GET или POST запрос.
В таком случае, если не получается забрать сведения, нужно дальше сидеть и думать, что в вашем парсинге не так.
Суть задачи простая. Ввести что-то в инпут, далее ваш контроллер отправляет запрос, находит и возвращает сведения к вам на view.
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Re: Асинхронное получение данных из textInput

Сообщение andrej3337 »

Ну почему же, это же государственный регистрирующий орган. Он как раз изначальный источник сведений из егр, вот их спецификация по api http://egr.gov.by/api/swagger-ui.html#/main-controller
У них на сайте не нашел каких-то дополнительных условий получения этих сведений, типо получения платного токена для доступа к апи http://egr.gov.by/egrn/index.jsp?content=API
Поэтому увидев ошибку и погуглив, ситуация кажется немного странной. Тут либо запрос неправильно сформирован, либо через какие-то костыли его нужно отправлять.
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Асинхронное получение данных из textInput

Сообщение unknownby »

andrej3337 писал(а): 2020.09.14, 16:32 Ну почему же, это же государственный регистрирующий орган. Он как раз изначальный источник сведений из егр, вот их спецификация по api http://egr.gov.by/api/swagger-ui.html#/main-controller
У них на сайте не нашел каких-то дополнительных условий получения этих сведений, типо получения платного токена для доступа к апи http://egr.gov.by/egrn/index.jsp?content=API
Поэтому увидев ошибку и погуглив, ситуация кажется немного странной. Тут либо запрос неправильно сформирован, либо через какие-то костыли его нужно отправлять.
Забил обычный URL и выдало инфу
http://egr.gov.by/api/v2/egr/getAddress ... /791057535
"Сухари-Ромашка"
Просто кто-то не дописал в URL "api/"
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Re: Асинхронное получение данных из textInput

Сообщение andrej3337 »

Ребят, опять я застрял. Опишу вышеуказанную проблему подробнее. При запросе данных аяксом с чужого ресурса, предоставляющего их по api, возникает ошибка в их получении

Код: Выделить всё

Access to XMLHttpRequest at 'http://egr.gov.by/api/v2/egr/getShortInfoByRegName/%D0%B3%D0%BE%D0%BC%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BC%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%B0%D0%BB%D1%8B' from origin 'http://......com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Единственным нормальным решением видится использовать прокси сервер, который бы подставлял нужные заголовки. Для целей разработки в браузерах решают проблему дополнения или бесплатные прокси (нашел 3 таких), но все же это так себе заплатки. Нужно развернуть свой. И с этим проблемы, ставил по мануалам, но ничего не проходит.

Возможно я не понимаю принципов по которым они работают. Есть у меня centos 7, использую бесплатную панельку brainyCP.
Развертывал по этим мануалам:
1. https://github.com/Rob--W/cors-anywhere/#documentation
2. https://github.com/gnuns/allorigins
3. https://github.com/caltechlibrary/corsp ... /README.md

Вот по третьему варианту самый понятный мануал, вроде и служба запущена и работает, а все равно запросы не проходят.
Общий принцип у них следующий, в конфиге есть по умолчанию:
ip "0.0.0.0" и порт 8080 - как мне их редактировать если у меня допустим есть поддомен.домен.ру на айпишнике скажем 222.32.24.1 и добавил я порт 8000. Чтобы через прокси пошли запросы мне нужно указать вместо первоначальных данных ip "222.32.24.1" и порт 8000? Или можно ip "поддомен.домен.ру" и порт 8000? или это вообще не менять?

Для того чтобы данные прошли с нужными заголовками необходимо при этом перед урлом запроса http://egr.gov.by/api/v2/egr/getShortInfoByRegName/ подставить свой прокси вида: "http://поддомен.домен.ру:8000/egr.gov.b ... ByRegName/"
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Re: Асинхронное получение данных из textInput

Сообщение andrej3337 »

andrej3337 писал(а): 2020.09.21, 18:13 Ребят, опять я застрял. Опишу вышеуказанную проблему подробнее. При запросе данных аяксом с чужого ресурса, предоставляющего их по api, возникает ошибка в их получении

Код: Выделить всё

Access to XMLHttpRequest at 'http://egr.gov.by/api/v2/egr/getShortInfoByRegName/%D0%B3%D0%BE%D0%BC%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BC%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%B0%D0%BB%D1%8B' from origin 'http://......com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Единственным нормальным решением видится использовать прокси сервер, который бы подставлял нужные заголовки.

Возможно я не понимаю принципов по которым они работают. Есть у меня centos 7, использую бесплатную панельку brainyCP.
Развертывал по этим мануалам:
3. https://github.com/caltechlibrary/corsp ... /README.md

Вот по третьему варианту самый понятный мануал, вроде и служба запущена и работает, а все равно запросы не проходят.
Методом ненаучного тыка, путем отключения файервола, установлено, что прокси в 3-ем варианте действительно правильно установлен и работает с настройками ip "0.0.0.0" и порт 8080 (порт, который добавил) в конфигурационном файле и с урлом запроса вида "https://поддомен.домен.ру:8080/egr.gov. ... ByRegName/"

Теперь надо разобраться как указать файерволу не блокировать этот порт и поиграть с настройками тайм аута
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Асинхронное получение данных из textInput

Сообщение unknownby »

andrej3337 писал(а): 2020.09.22, 09:56 Теперь надо разобраться как указать файерволу не блокировать этот порт и поиграть с настройками тайм аута
Тебе бы подсказали, если бы кто-то здесь таким занимался :)
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Re: Асинхронное получение данных из textInput

Сообщение andrej3337 »

unknownby писал(а): 2020.09.22, 14:26
andrej3337 писал(а): 2020.09.22, 09:56 Теперь надо разобраться как указать файерволу не блокировать этот порт и поиграть с настройками тайм аута
Тебе бы подсказали, если бы кто-то здесь таким занимался :)
Уже загуглил, сегодня-завтра поиграюсь
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Асинхронное получение данных из textInput

Сообщение unknownby »

andrej3337 писал(а): 2020.09.21, 18:13 Ребят, опять я застрял. Опишу вышеуказанную проблему подробнее. При запросе данных аяксом с чужого ресурса, предоставляющего их по api, возникает ошибка в их получении
А в чем собственно ошибка?
Есть твой сайт, есть чужой сайт. Со своего обращаешься через ajax и он возвращает то, что вернул бы по конкретному URL чужой сайт.

Код: Выделить всё

$.ajax({
            type: 'POST', //тип передачи данных
            url: 'MY_URL', //нужный URL, куда мы обращаемся для данных
            data: {
                egr: my_egr, //передаем нужный идентификатор или что нужно под данный URL
            },
            success: function(result) {
                //возвращаем всю нужную информацию в див с классом my_class, вся информацию внутри result
                $('.my_class').html(result); 
            }
        });
В случае с EGR можно попробовать генерировать URL из основная_ссылка/тип_данных_запроса/идентификатор
Можно конечно через curl еще подключиться, выгрузить информацию и её через контроллер вернуть в представление :D

P.S.
Посмотрю что с заголовками можно сделать :D
Нашел, что можно добавить в ajax, дальше сам :)

Код: Выделить всё

beforeSend: function(xhr){xhr.setRequestHeader('Access-Control-Allow-Origin', 'my_site');},
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Re: Асинхронное получение данных из textInput

Сообщение andrej3337 »

Так вот неделю гуглю ищу решение. Как я понял это именно проблема защиты со стороны браузеров и проблема распространенная, в детали сильно не лез - эт для меня космос.

Курлом у меня достаются данные свободно и с ними там мне понятно и легко работать. А вот с аяксом на клиенте вылезла ошибка, как я выше указывал.

Для работы на локалке решает плагин для браузера, но когда зальешь на сайт и реальные пользователи начнут делать запросы, им же не напишешь установить плагин. Сторонние прокси могут забанить, если количество запросов будет большим, поэтому начал играться со своим прокси, с которыми ничего не получалось. Вот только прикинул, а не блокирует ли файервол запросы, вырубил, и быстро разобрался как получить данные, уже открыл используемый порт. Надо лишь мануал сервера почитать по настройкам, потому как вылезали во время тестирования ошибки, связанные с установленными ограничениями, ну эт не должно быть сложной задачей.
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Re: Асинхронное получение данных из textInput

Сообщение andrej3337 »

Код: Выделить всё

   <script>
$('#k1').on('input', function(){
        var data = $(this).val();
        if(data.length > 2){
                $.ajax({
                url: 'http://egr.gov.by/api/v2/egr/getShortInfoByRegName/'+data,
                type: 'GET',
                response: 'text',
                dataType: 'json',
                beforeSend: function(xhr){xhr.setRequestHeader('Access-Control-Allow-Origin', 'zachet.pro');},
                success: function(result) {
                var i = 0;
                for (i; i < result.slice(0,5).length; i++) {
                    console.log(result[i].vn||result[i].vfio);
                }
                }
                });
                }
});
</script>
Вложение чет не закрепляется, в консоли так

Код: Выделить всё

jquery.min.js:2 Mixed Content: The page at 'https://zachet.pro/' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://egr.gov.by/api/v2/egr/getShortInfoByRegName/%D0%B3%D0%BE%D0%BC%D0%B5%D0%BB%D1%8C'. This content should also be served over HTTPS.
send @ jquery.min.js:2
ajax @ jquery.min.js:2
(anonymous) @ (index):64
dispatch @ jquery.min.js:2
v.handle @ jquery.min.js:2
jquery.min.js:2 GET https://egr.gov.by/api/v2/egr/getShortInfoByRegName/%D0%B3%D0%BE%D0%BC%D0%B5%D0%BB net::ERR_SSL_PROTOCOL_ERROR
andrej3337
Сообщения: 46
Зарегистрирован: 2019.11.03, 16:02

Re: Асинхронное получение данных из textInput

Сообщение andrej3337 »

Код: Выделить всё

$('#k1').on('input', function(){
        var data = $(this).val();
        if(data.length > 2){
                $.ajax({
                url: 'https://api.zachet.pro:мойпорт/http://egr.gov.by/api/v2/egr/getShortInfoByRegName/'+data,
                type: 'GET',
                response: 'text',
                dataType: 'json',
                success: function(result) {
                var i = 0;
                for (i; i < result.slice(0,5).length; i++) {
                    console.log(result[i].vn||result[i].vfio);
                }
                }
                });
                }
});
</script>
Данные приходят, причем как на локалке, так и на живом сервере
СТ "Химик-2" Гомельского района
(index):75 КУП по обеспечению топливом "Гомельоблтопливо"
(index):75 Центральная поликлиника Гомельского отделения БЖД
(index):75 ООО "РНК Гомель"
(index):75 ОАО "Гомельский центр восточных единоборств"
(index):75 ГСПК № 32 Советского района г. Гомеля
(index):75 Ясли-сад №117 г. Гомеля
(index):75 Ясли-сад № 64 г. Гомеля
(index):75 ГСК №36 Центрального района г.Гомеля
(index):75 Ясли-сад № 83 г. Гомеля
(index):75 ГСПК № 32 Советского района г. Гомеля
(index):75 Ясли-сад №117 г. Гомеля
(index):75 Ясли-сад № 64 г. Гомеля
(index):75 ГСК №36 Центрального района г.Гомеля
(index):75 Ясли-сад № 83 г. Гомеля
(index):75 ГСПК № 32 Советского района г. Гомеля
(index):75 Гоманков Вячеслав Александрович
(index):75 Ясли-сад №117 г. Гомеля
(index):75 Ясли-сад № 64 г. Гомеля
(index):75 ГСК №36 Центрального района г.Гомеля
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Асинхронное получение данных из textInput

Сообщение unknownby »

andrej3337 писал(а): 2020.09.22, 18:08 Данные приходят, причем как на локалке, так и на живом сервере
При помощи curl реализовалось легко, без косяков с передачей заголовков.
Во вьюхе, есть текстовое поле с айди my_input

Код: Выделить всё

<div class="my_class">
</div>
<?php
$js = "
$(document).ready(function(){

    $('#my_input').on('input', function(e){
        $.ajax({
            type: 'POST',
            url: 'api',
            data: {
                num: $(this).val(),
            },
            success: function(result) {
                $('.my_class').html(result); 
            }
        });
    });

});
";
$this->registerJs($js);
?>
Контроллер

Код: Выделить всё

    public function actionApi()
    {
        $num = \Yii::$app->getRequest()->post('num');
        $url = 'http://egr.gov.by/api/v2/egr/getAddressByRegNum/'.$num;
        $handle = curl_init();

        curl_setopt($handle, CURLOPT_URL, $url);
        curl_setopt($handle, CURLOPT_POST, false);
        curl_setopt($handle, CURLOPT_BINARYTRANSFER, false);
        curl_setopt($handle, CURLOPT_HEADER, true);
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, false);

        $response = curl_exec($handle);
        $hlength  = curl_getinfo($handle, CURLINFO_HEADER_SIZE);
        $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
        $body     = substr($response, $hlength);

        // завершение сеанса и освобождение ресурсов
        curl_close($handle);

        // If HTTP response is not 200, throw exception
        if ($httpCode != 200) {
            //throw new Exception($httpCode);
            return false;
        }

        return $body;
    }
Пример возврата

Код: Выделить всё

[{"ngrn":791057535,"dfrom":"2017-04-09T21:00:00.000+00:00","nkstran":112,"nindex":213116,"nksoato":7244856056,"vregion":"Могилевская","vdistrict":"Могилевский","nktnp":15,"vnp":"Сухари","nktul":1,"vulitsa":"Чаусская","vdom":"2","vtels":"8295456300, 80296094189","nsi00201":{"vnstranp":"Республика Беларусь","nkstran":112,"nsi00201":4881},"nsi00202":{"vnsfull":"Могилевская область Могилевский район Сухаревский сельсовет аг. Сухари","objectnumber":24995,"nksoato":7.2448558E9,"nsi00202":361524},"nsi00239":{"vntnpk":"аг.","vntnpp":"агрогородок","nktnp":15,"nsi00239":64923},"nsi00226":{"vntulk":"ул.","vntulp":"улица","nktul":1,"nsi00226":33295},"ngr04003":237244742,"dcrta":"2017-04-09T21:00:00.000+00:00","cact":"+","cincl":"+"}]
Ответить