Какие правила HTML придерживаются при построении параметров?
Я использую Rails для автоматического создания магических объектов на основе сложного набора вложенных атрибутов. Поэтому мне нужно, чтобы параметры были вложены очень определенным образом. Очевидно, я понимаю, что могу их построить, но хочу с JS, но я бы хотел, чтобы форма формы автоматически помогала в строительстве. Для контекста у меня есть 2 столбца, представленных 2 <td>
s. Каждый столбец может либо создать новую запись, либо отредактировать существующую запись. Конечно, когда существующая запись должна быть изменена, идентификатор записи должен быть передан.
Представленный HTML выглядит следующим образом:
<td width="50%" style="padding-right:3%" class="logistic-details" data-type="logistics" data-typelogistics="delivery" data-instructions="test instructions" data-id="1" data-amount="20">
<span class="area-to-inject-amount-inputs" data-object="type_logistics" data-type="logistics" data-typelogistics="delivery">
<input class="labeler-response" name="type_logistics_attributes[][id]" type="hidden" value="1">
<input class="labeler-response" name="type_logistics_attributes[][instructions]" type="text" value="test instructions">
</span>
</td>
<td width="50%" style="padding-right:3%" class="logistic-details" data-type="logistics" data-typelogistics="pickup" data-instructions="" data-id="" data-amount="0">
<span class="area-to-inject-amount-inputs" data-object="type_logistics" data-type="logistics" data-typelogistics="pickup" data-actioned="charged">
<input type="hidden" name="type_logistics_attributes[][type_of_logistics]" value="pickup">
<input class="injected-amount-input" type="number" min="0" max="" placeholder="Amount" name="type_logistics_attributes[][charged_amounts_attributes][][amount]" value="20">
<span class="area-to-inject-type-of-amount">
<input type="hidden" name="type_logistics_attributes[][charged_amounts_attributes][][type_of_amount]" value="logistics">
</span>
<input class="labeler-response" name="type_logistics_attributes[][instructions]" type="text" placeholder="Enter address and instructions">
</span>
</td>
В этом случае первый <td>
изменяет существующую запись с идентификатором 1, а второй <td>
предоставляет параметры для создания новой записи. Когда создается новая запись, также создается дочерний элемент charged_amounts
. Таким образом, это параметры, которые я ожидал бы:
"type_logistics_attributes"=>[
{"id"=>"1", "instructions"=>"test instructions"},
{"type_of_logistics"=>"pickup", "charged_amounts_attributes"=>[{"amount"=>"40", "type_of_amount"=>"logistics"}], "instructions" => "123 Fake street"}
]
Вместо этого я получаю следующее:
"type_logistics_attributes"=>[
{"id"=>"1", "type_of_logistics"=>"pickup", "instructions"=>"test instructions", "charged_amounts_attributes"=>[{"amount"=>"40", "type_of_amount"=>"logistics"}]},
{"instructions"=>"123 Fake street"}
]
Как-то граница <td>
не работает, а дочерние атрибуты charged_amount
каким-то образом были сосредоточены в первой модификации существующей записи <td>
.
Спасибо!
Ответы
Ответ 1
Это не <td>
или какой-либо подобный элемент HTML, который создает "границу" для входов, это элемент <form>
. Все входы, которые находятся в теге <form>
, отправляются браузером в качестве параметров при отправке формы. Вероятно, у вас есть оба столбца в одном <form>
, поэтому параметры из обоих столбцов смешиваются в params
.
Ответ 2
Единственный способ, с помощью которого вы можете получить оба параметра в одной форме, но вложенные по-другому, - это то, что если вы предоставите некоторый идентификатор в новое поле ввода. Именно это отличает элементы массива type_logistics_attributes
.
У меня была аналогичная потребность, и я использовал вложенную форму ryanb. Когда я использую его с той же целью, что и ваша, что он делает, он предоставляет случайный идентификатор для нового поля ввода. Вот как он дифференцируется.
Надеюсь, это поможет вам в правильном направлении.
Ответ 3
Я не уверен, что есть способ сделать это специально, как вы хотите, но вы можете заставить params выглядеть так:
"type_logistics_attributes"=>[
{"id"=>"1", "instructions"=>"test instructions"},
{"id"=>"1", "type_of_logistics"=>"pickup", "charged_amounts_attributes"=>[{"amount"=>"40", "type_of_amount"=>"logistics"}], "instructions" => "123 Fake street"}
]
Вы можете достичь этого, добавив здесь дополнительный скрытый входной идентификатор:
<td width="50%" style="padding-right:3%" class="logistic-details" data-type="logistics" data-typelogistics="pickup" data-instructions="" data-id="" data-amount="0">
<span class="area-to-inject-amount-inputs" data-object="type_logistics" data-type="logistics" data-typelogistics="pickup" data-actioned="charged">
<input name="type_logistics_attributes[][id]" type="hidden" value="1">
<input type="hidden" name="type_logistics_attributes[][type_of_logistics]" value="pickup">
<input class="injected-amount-input" type="number" min="0" max="" placeholder="Amount" name="type_logistics_attributes[][charged_amounts_attributes][][amount]" value="20">
<span class="area-to-inject-type-of-amount">
<input type="hidden" name="type_logistics_attributes[][charged_amounts_attributes][][type_of_amount]" value="logistics">
</span>
<input class="labeler-response" name="type_logistics_attributes[][instructions]" type="text" placeholder="Enter address and instructions">
</span>
</td>
У Rails есть правило для обработки этого: оно берет атрибуты слева направо в querystring (или сверху вниз в вашем HTML) и создает новый объект каждый раз, когда он видит повторяющийся атрибут.