Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Список с многоуровневой зависимостью (https://javascript.ru/forum/dom-window/66979-spisok-s-mnogourovnevojj-zavisimostyu.html)

dfii 21.01.2017 11:34

Список с многоуровневой зависимостью
 
Вложений: 1
Я не программист, я по железу.
Но прижало и возникла необходимость создать для поступающей на ремонт техники создать небольшую бд.
Для регистрации техники выбираем из динамических списков сначало отдел, далее с помощью javascript для второго окна формируется список категории техники отфильтрованный в запросе во выбранному ранее отделу, список для третьего окна должен фильтроваться как по выбранной категории, так и по выбранному отделу, но вот как получить значение выбраного отдела ума не приложу. Чтобы закончить свой проект, осталось решить только эту задачу, но времени в связи с загруженностью на изучение теории нет. Данные задачи приложил. Данные в бд для простоты урезал.

laimas 21.01.2017 17:54

Ничего не напутано в представлении данных?

dfii 22.01.2017 07:20

Ткни носом на сомнительное место

laimas 22.01.2017 07:43

Здесь не место, а подход к представлению данных. Откуда тут могут взяться многоуровневые списки, если набор 'Контрольный', 'Планировочный', 'Сдаточный', 'Приёмочный' характеризует видимо этапы ремонта, а набор 'ИБП', 'Монитор', 'Принтер', 'Системник', 'Сканер', это категория техники принятой на ремонт, и оба этих набора есть разные сущности?

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

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

dfii 22.01.2017 11:24

Приемочный, сдаточный, контрольный и т.д. это гипотетические отделы. Писать реальные отделы посчитал не желательным. Извеняюсь что ввёл в заблуждение своей фантазией :write:

Код формы:
[spoiler]
<html>
<head>
<meta charset="utf-8" />
<title>Ремонт - Поступление</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="selects.js"></script>
</head>
<body>
<?php
	function sp_otdel()      {
                $dbc = mysqli_connect ('localhost', 'root', '', 'select3');
                $query = "SELECT * FROM tbl_otdel ORDER BY name";
                $query_res = mysqli_query ($dbc, $query);
                $sp_otdel = array();
                while($row = mysqli_fetch_assoc($query_res))    {
                        $sp_otdel[] = $row;                              }
                return $sp_otdel;        }
        $sp_otdel = sp_otdel();
?>
	<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
                <select name='sp_otdel' id='sp_otdel'>
                <option value="0"> - Выберите отдел - </option>
                <?php foreach($sp_otdel as $item)       {echo "<option value='".$item['id']."'>".$item['name']."</option>";} ?>
                </select><br /><br />
                
                <select name='sp_category_tech' id='sp_category_tech' disabled="disabled">
     		<option value="0"> - Выберите категорию - </option>
                </select><br /><br />

                <select name='sp_num_tech' id='sp_num_tech' disabled="disabled">
	         	<option value="0"> - Выберите номер - </option>
                </select><br /><br />
	</form>
</body>
</html>
[/spoiler]

Первый список формируется функцией при загрузке формы, после выбора значения в первом поле срабатывает скрипт и на основе этого значения формирует список категорий техники принадлежащий выбранному отделу. Второй список формируется кодом:
[spoiler]
<?php
$sp_otdel = @intval($_GET['sp_otdel']);
$dbc = mysqli_connect ('localhost', 'root', '', 'select3' );
$query = "SELECT tbl_number_tech.*, tbl_category.* FROM tbl_number_tech, tbl_category WHERE tbl_number_tech.id_location = $sp_otdel AND tbl_category.id = tbl_number_tech.id_category_tech GROUP BY tbl_category.category";
$regs = mysqli_query($dbc, $query);
if ($regs) {
    $num = mysqli_num_rows($regs);      
    $i = 0;
    while ($i < $num) {
       $sp_category_tech[$i] = mysqli_fetch_assoc($regs);   
       $i++;
    }     
    $result = array('sp_category_tech'=>$sp_category_tech);  
}
else {
	$result = array('type'=>'error');
}
print json_encode($result); 
?>
[/spoiler]

Результат выборки возвращается обратно в JavaScript, откуда в форму в виде HTML кода.
После выбора категории техники на основе значения ПЕРВОГО и второго полей должен сформироваться третий список, НО значения второго поля я передаю по аналогии первой функции javascript'a, но вместе с со значением второго поля не могу передать значение ранее выбранного первого поля.
Этот код ждёт значения обеих предыдущих полей:
[spoiler]
<?php
$sp_category_tech = @intval($_GET['sp_category_tech']);
$sp_otdel = ; // Сюда нужно передать значение первого поля
$dbc = mysqli_connect ('localhost', 'root', '', 'select3' );
$query = "SELECT * FROM tbl_number_tech WHERE id_category_tech = $sp_category_tech AND id_location = $sp_otdel";
$regs = mysqli_query($dbc, $query);
if ($regs) {
    $num = mysqli_num_rows($regs);      
    $i = 0;
    while ($i < $num) {
       $sp_num_tech[$i] = mysqli_fetch_assoc($regs);   
       $i++;
    }     
    $result = array('sp_num_tech'=>$sp_num_tech);  
}
else {
	$result = array('type'=>'error');
}
print json_encode($result); 
?>
[/spoiler]

Ещё меня немного удивила одно выражение в теме Формирование связанных списков select произвольной вложенности, где в начале статьи приводится:
Цитата:

Для двух зависимых списков (я публиковал пример более 5 лет назад!) ситуация простая и понятная, но люди задают вопрос — а как развить пример для вложения 3х списков?
Ответ — никак. :) Придется менять практически все, потому слово — менять тут не подходит.
Более конкретно:
[spoiler]
$('#sp_category_tech').change(function () { // Функция запускает скрипт при изменении поля sp_category_tech
var sp_category_tech = $(this).val(); // Инициализирует переменную sp_category_tech и передаёт ей значение второго поля
var sp_otdel = $('sp_otdel').val(); // Тут переменной sp_otdel по замыслу должно быть передано значение первого поля, но этого не происходит.
... // тут всякий дисабл для полей
var url = 'get_num_tech.php'; // объявляется переменная url  с именем скрипта для фомирования третьего списка
$.get(url, "sp_category_tech=" + sp_category_tech, // тут смутно представляю что с помощью get должен запуститься скрипт, которому передаются значения выбраных полей, но как это воплотить в код?
[/spoiler]

laimas 22.01.2017 11:49

Не майтесь хренью, а ответьте себе на вопрос - что должна содержать база? Если записи когда, от кого, какая техника поступила на ремонт, и ее сопровождение по циклу ремонта, то зачем все это, что только усложняет все, и пользы никакой нет?

Какая к черту разница гипотетические ли названия или реальные. Нет в принципе вообще многоуровневых списков в контексте select, есть связанные списки. Но связанные списки потребуются только тогда, когда в наличие есть дерево, той же категории техники. У вас этого нет, и все что вы пишите, это бесполезная трата ресурсов сервера и клиента.

dfii 22.01.2017 12:59

я не программист, языков не знаю, а беру готовые примеры и подставляю свои данные.
В бд есть три таблицы.
1. Содержит перечень отделов
2. Содержит перечень категорий техники
3. Содержит номера техники, id отдела, к которому принадлежит, id категории техники к которой относится

Чтобы не производить ручной ввод данных первый список даёт возможность сузить возможные номера техники выбранным отделом, к которому эта техника пренадлежит, второй список всю технику выбранного отдела сортирует по категориям, например все принтеры бухгалтерии, в котором их 5 с номерами 107, 104, 108, 207, 301. Во первых я исключаю этим опечатку во время заполнения акта приёма, во вторых контролирую принадлежность техники данному отделу. Бывало что принтер одного отдела долгие месяцы использовал второй отдел, а так как при использовании 200 принтеров одной марки сами пользователи могли и не заметить подмены. Во вторых, пользователи могли бы следить за судьбой своего принтера через запросы в бд.

Как вы решение этих проблем предложите сделать проще?

пс: Реализовать это через перезагрузку форм проблемы нет. Но как это сделать с помощью одной формы и динамических списков?

laimas 22.01.2017 14:06

Во вложении есть дамп базы. В нем простой список отделов, а также простой список техники. Оба списка не являются деревьями, то есть не имеют зависимостей. В третье таблице не понятно что к чему, какие-то номера....

Предположим, что принимается на ремонт техника, для простоты: Принтеры, Компьютеры, Сканеры. Техника может распределяться между тремя отделами: Первый, Второй, Третий. Пусть эти списки постоянны и не изменяются, что в общем не так важно, к примеру если перечень техники может изменяться, то тогда его держать как отдельную таблицу.

Достаточно для хранения такой записи иметь единственную таблицу заказов (туман, что есть 5 с номерами 107, 104, 108, 207, 301, в примере это поле `number`):

CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Номер заказа',
  `groups` enum('Первый','Второй','Третий') NOT NULL COMMENT 'Отделы',
  `mechanism` enum('Компьютеры','Сканеры','Принтеры') NOT NULL COMMENT 'Техника',
  `number` int(11) NOT NULL COMMENT 'Идентификатор техники',
  `customer` varchar(120) NOT NULL COMMENT 'Заказчик',
  `defect` varchar(1000) NOT NULL COMMENT 'Описание дефекта',
  `performer` varchar(64) NOT NULL COMMENT 'Исполнитель работ',
  `receipt_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Дата поступления',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Список заказов' AUTO_INCREMENT=1;



Соответственно форма приема заказов должна содержать поля для заполнения: number, customer, defect, performer и два списка (select) описывающих массивы [1=>'Первый','Второй','Третий'] и [1=>'Компьютеры','Сканеры','При нтеры'].

Заполнение формы, это выбор в списке раздела, категории техники, и указания остальных значений в полях формы.

При получении формы запись получит номер заказа и автоматически дату поступления заказа как текущую дату.

Если убрать из таблицы поля customer, defect, performer, receipt_date, то заполнять ничего не требуется, кроме указания какого-то номера (?). При этом делать какие либо запросы не понятно за какими списками не требуется.

Вывод содержимого этой таблицы можно производить по любому из параметров - фильтр. Это могут быть списки только по отделу со всей его техникой, либо по конкретной технике, по дате поступления и т.д., и т.п. То есть по известным полям формы задаются параметры запроса: выбор в списках, задание условия, например равно дате, либо больше даты и прочее.

Чтобы построить базу данных, нужно понимать задачу решаемую. Для примера описанного выше этой таблицы вполне хватит. И из вашего представления не видно того, чтобы требовалась какая-то последовательная выборка не понятно чего и зачем. А из описанного вообще не понять деталей.

dfii 22.01.2017 14:45

Безусловно ваши советы при разработке хранения и использования данных мне пригодятся, за что вам выражают благодарность.
Но я всего лишь хотел узнать как в Javascript получить из формы значения двух полей и передать их для обработки запроса, видимо пока это останется непознаным.
Под отделами в базе я имел ввиду не отделы по ремонту техники, а отделы, которые участвуют в их "истреблении" и которые их на ремонт и отправляют. То что кажется в бд излишним для вас, для меня на практике экономит время и нервы, так как "оптимизация" затрат на производстве привела к тому что работы стало так много и такой разнообразной что приходится и принимать на ремонт и ремонтировать и подключать и настраивать, учить пользоваться, обеспечивать связь, консультировать и отчитываться в лице одного. Поэтому, чтобы избавить себя от бесконечных звонков "как там мой принтер с цветочком на лотке? когда будет готов? Что с ним было?" пользователи открывают страничку и видят в режиме реального времени состояния своего любимца.
Кстате в реале отделов полсотни и техники тысячи единиц.

laimas 22.01.2017 15:04

Хотите получить ответы, описывайте задачу не абстрактно, а как есть. Правда, если задачей является администрирование, то это не простой вопрос и простой на него ответ. Это скорее работа, и если нет опыта, то лучше заказать таковую.

Из того, что описано вами, то что вы пытаетесь сделать, это пустое никчемное занятие. К примеру, если их 5 принтеров с номерами .... означает равномерное распределение нагрузки, то запрашивать что-то последовательно все равно не требуется. В данном случае сперва надо выбрать в списке Техника, и пока нет в нем выбора, выбор в списке Отдел не разрешается, что обеспечит JS. Выбор в списке Техника автоматически отправляет асинхронный запрос на сервер с параметрам - ID техники. Сервер выбирает, подсчитывая количество записей у каждого раздела для указанного ID техники (по примеру мной приведенному, это WHERE mechanism=ID запроса). Возвращается и отображается список, по которому можно судить кому отдать технику.

Или, к примеру, заказы не просто принимаются, но и ведется база данных заказчиков: ФИО, адрес, телефон. Если заказчик уже был вашим клиентом, то достаточно ввести, к примеру, его номер телефона, если такой будет найден в базе, данные заказчика автоматически будут заполнены в форме. Либо при вводе фамилии/адреса в фоновом режиме происходит опрос базы и предлагаются имеющиеся адреса/фамилии. Это называется атозаполнением и работает в фоновом режиме.

Из представленного вами ранее нет никакой причины что-то выковыривать последовательно, да еще и отображать в каких то отдельных окнах. А последнее говорит о гораздо больших задачах, которые нужно решать. Но если таковые задачи ставятся, то и подход к ним должен быть не такой примитивный, как вы пытаетесь делать.

dfii 22.01.2017 16:00

Извините меня конечно, но видимо на свой конкретный вопрос как передать значение, кроме критики о вреде абстрактно-примитивного взгляда на построения кода в мире программирования я ничего не получу. Буду абстрагироваться в своём примитивном мире железа самостоятельно, хотя надеялся что кто-нибудь протянет хоть ножку помощи, а получил кирпич критики :)
Не принимайте мои слова на свой личный счёт, как сожалению это явление повсеместное и в профессиональной среде встречается чаще чем где-либо.

laimas 22.01.2017 16:15

Цитата:

Сообщение от dfii
свой конкретный вопрос как передать значение, кроме критики о вреде абстрактно-примитивного взгляда на построения кода в мире программирования я ничего не получу.

Все запросы к серверу, это GET/POST и прочее параметры, как ключ=значение. Надо от двух списков передать значения для сервера, ну так какая проблема: имя_списа1=значение_списка_1 &имя_списа2=значение_списка_ 2. Это ни есть проблема.

Цитата:

Сообщение от dfii
Не принимайте мои слова на свой личный счёт

Я не из обидчивых мальчиков в коротких штанишках. И вам не советую думать, что вас тут критикой хотят убить. Вам советуют подумать, прежде чем делать то или иное. А данные которые вы описали, ну никак не тянут на то, чего вы хотите делать с ними. Это просто усложнение простого.

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

dfii 22.01.2017 16:28

Цитата:

Это ни есть проблема.
Ну если это не проблема, то как бы вы подправили предложенный select.js, чтобы с помощью уже используемого get передать значение не одного второго поля, а сразу двух для формирования третьего списка?

laimas 22.01.2017 16:38

$('form').submit(function(e) {
    e.preventDefault();
    $.get(this.action, $(this).serialize(), function(data) {
        //ответ сервера
    })
})

dfii 23.01.2017 03:22

О, буду жевать ваш код, сразу мне не понятно что к чему, огромное спасибо!

Кстате, озарило вчера, можно создать табличку для хранения оперативных данных, заносить туда значение полей, пользоваться ими в процессе заполнения формы а при отправки данных с формы в бд табличку чистить DELETE FROM.

laimas 23.01.2017 08:02

Цитата:

Сообщение от dfii
сразу мне не понятно что к чему

Что к чему

Что такое оперативные данные, зачем их хранить в таблице, секрет для всех. Ну если надо, на здоровье.

dfii 23.01.2017 10:16

Оперативные данные в моём понятие это переменные в рамках, в моём случае, заполнения формы.
Когда получаю значение первого поля, вставляю в таблицу temp бд, также значение второго и т.д. по необходимости.
После того как данные с помощью формы сохраняю в бд очищаю таблицу temp (ну чтобы база не забивалась).

laimas 23.01.2017 10:38

Как и с получением чего-то по спискам, не понятно для чего, так и с какими то переменными, которые нужно хранить, тоже ничего не понятно.

Есть, к примеру, последовательный прием данных от клиента, например, заполнили форму каким либо выбором, отправили серверу, сервер это сохранил, и для этого может и сессии хватит. Далее клиенту отдается следующая форма, где нужно заполнить свои данные. Отправление этих данных есть сигнал серверу сохранить ранее запомненное и вновь полученное.

Такое делается если большой набор данных, и чтобы облегчить навигацию по ним, заполнение формы разбивают на этапы, при этом всегда можно вернуться назад по этапам.

Существует также понятие как кеширование, которое к контексте "запросить сервер" есть клиентское понятие.

Чего вы там пытаетесь хранить, да еще в контексте ранее описанного, даже представить трудно. Ну коли надо, никто не запрещает, но и возможно вы опять делаете лишние никчемные операции.

dfii 24.01.2017 03:56

Цитата:

Сообщение от laimas (Сообщение 442002)
тоже ничего не понятно.
...
возможно вы опять делаете лишние никчемные операции.

Мне кажется из того что ничего не понятно всё же не надо делать вывод что это опять же никчёмно. Возможно вам бы следовало научиться понимать о чём говорят, ну или хотя бы как то стремиться к этому, а потом уже делать выводы о нужности того или иного действия. А в целом всё же по теории проектирования перспективных прикладных проектов в организации хранения данных в релятивиских базах данных вы оказываете большую помощь!

laimas 24.01.2017 10:26

Цитата:

Сообщение от dfii
Возможно вам бы следовало научиться понимать о чём говорят, ну или хотя бы как то стремиться к этому

Вам не кажется, что вы пишите с позиции не понятого гения? )

Я сужу только по тому, что вижу. Если говорить по первому, то не видно смысла в действиях вами предпринимаемых, ибо у вас простые зависимости, а не дерево, и получить их можно сразу, одним запросом к базе. Что было мной и высказано.

Цитата:

Сообщение от dfii
озарило вчера, можно создать табличку для хранения оперативных данных, заносить туда значение полей, пользоваться ими в процессе заполнения формы а при отправки данных с формы в бд табличку чистить DELETE FROM

Зачем тогда делится этим? Что это, зачем хранить и почему именно для этого нужно нагружать sql-сервер? Допустим хранить, а почему не сессия, которая сама умрет? И вообще может и хранить не надо, есть http_build_query(), может и этого вполне достаточно будет? А не зная по поводу чего вас озарило, можно только предполагать. Так какие претензии могут быть?

dfii 24.01.2017 16:40

Дак я же не с претензий тему начал, да и в ходе беседы её не выражал, а лишь искал помощи. Просто выразил мнение об вашем отношении к моей проблеме. Вы слишком требовательны к нубам. Вопрошающий, который вас может удовлетворить своим вопросом должен предварительно хорошо подготовиться.
Про свои комплексы слышу впервые, поинтересуюсь у знакомых, может что и скрывают от меня :)

Извеняюсь за оффтоп. Кстате да, "последнее слово за мной" - страдаю :)

laimas 24.01.2017 17:12

Цитата:

Сообщение от dfii
Вы слишком требовательны к нубам

Я от вас ничего не требую, и мне в общем то как-то по... как там будет сделано, но... Если задается структура данных, показан код работы с ними, при этом из изложенного совсем не понятна цель мытарств, которых в общем-то не должно быть, что я должен сказать?

Вот каков бы был ваш ответ на такой мой пост: "сегодня меня посетила мысль, а что если то, что у меня есть я умножу на два и отниму половину, это будет нормально"?

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

Или чего вы ожидали?

Если вы разобрались "что к чему" в запросе клиента к серверу, то должны понять, что код передает все элементы формы серверу, коими у вас по коду являются только списки. А это означает, что всегда будут передаваться все списки не зависимо от того был ли в них выбор. Попутно можно заметить, что у опций по умолчанию (Выберите категорию и т.п.) значение лучше определять ни как 0, а как пустое, так как в этом случае проще проверить был ли выбор в списке.

Но не это суть. Пусть в списках был выбор, если на сервере удалить из набора данных списки с не выбранными опциями, то сервер будет запрашивать только то, что будут в наборе. Это означает, что не важно как будут передаваться данные формы, все ли сразу, или же при каждом изменении списка, катастрофы не произойдет, так как запросы данных определяются ключами запроса слева направо. А из этого следует, что можно установить нужный набор этих ключей (выбрав опции), сделать единственный запрос, а ответ, если уж так надо распихать на клиенте куда и как душа пожелает.

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

Запросы к SQL, это всегда есть "больное место" веб приложения, их оптимизируют, их не используют когда в этом нет причины. Нуб, не нуб, это не мне разбираться, но уж коли взялись писать, ну так надо как минимум понимать, что база, это не обязательно единственный ящик для всего что угодно, данные можно хранить и вне базы. Поэтому ответ на "многие Х в вопросе" может быть таким каким я его и пишу. А уж вам думать, что есть из этого золотое сечение, что оправдано, а что нет.

dfii 25.01.2017 16:41

На одном из форумов получил прямой ответ на вопрос, для тех кто ищет подобное решение:
$('#sp_category_tech').change(function () {
var sp_category_tech = $(this).val();
var sp_otdel = $('#sp_otdel').val();
		 if (sp_otdel == '0') {
   ...
$.get(
	url, 
	"sp_category_tech=" + sp_category_tech + "&sp_otdel=" + sp_otdel,

Спасибо всем!

laimas 25.01.2017 23:29

Цитата:

Сообщение от dfii
для тех кто ищет подобное решение

$('form').on('change', 'select', function() {
    var f = $(this).closest('form');    
    $get(f.attr('action'), f.serialize(), ...
})


Сервер:

if($get = array_diff(array_map('intval', $_GET), [0])) {
     //...
}


Часовой пояс GMT +3, время: 06:04.