Какие правила 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) и создает новый объект каждый раз, когда он видит повторяющийся атрибут.