How to loop through div per div

Viewed 106

Horrible title aside, I currently have a dynamic form that has tasks, and per tasks, statuses. The amount of tasks and status can vary. What I'm trying to do is submit the task name, status name, and colors tied to that status.

<form>
    <div class='task'>
        <input type="text" name="taskName[]" value="Task name">            
        <input type="text" name="status[]" class="pill gray" value="Status name">
        <input type="text" name="status[]" class="pill blue" value="Status Name">
        <input type="text" name="status[]" class="pill orange" value="Status Name">
        <button>Add Status</button>
    </div>
    <div class='task'>
        <input type="text" name="taskName[]" value="Task name">
        <input type="text" name="status[]" class="pill red" value="Status name">
        <input type="text" name="status[]" class="pill yellow" value="Status Name">
        <button>Add Status</button>
    </div>
    <button>Add Task</button>
</form>

I'm submitting the form via js and the only different thing is creating an array from the colors.

let colors = [];
for (let i = 0; i < tasks.length; i++) {
    const element = statuses[i];
    let pills = element.querySelectorAll('.pill');
    pills.forEach(element => {
        colors.push([element.classList[1]]);
    });
}

// Submit form
formData = new FormData(form);
formData.append("colors", colors);
// Ajax to php

On the php page, I'm able to loop through the tasks, but I'm not sure how to loop through the statuses correlating to that task. Currently per task it shows all status.

$taskName_array = isset($_POST['taskName']) ? $_POST['taskName'] : array();
$colors_array = isset($_POST['colors']) ? $_POST['colors'] : array();
$colors_array = explode(',', $colors_array);
// This outputs:
//  Array
// (
//     [0] => Gray
//     [1] => Blue
//     [2] => Orange
//     [3] => Red
//     [4] => Yellow
// )
$total_rows = count($taskName_array);

for ($i = 0; $i < $total_rows; $i++) {
    echo $taskName_array[$i];

    // Begin loop through status (Expecting not all statuses just the ones in the same div)
    for ($a = 0; $a < $colors_array ; $a++) {
        // I'm aware this would echo all the colors (not what I want) vs just the corresponding colors.
        echo $colors_array[$a];
    } 
}

Expected outcome would be something like "Task1-gray, blue, orange | Task2-red, yellow" Let me know if that's unclear or if you need more.

2 Answers

One way to achieve this is to add hidden input and assign color value to it . i.e

<div class='task'>
  <input type="text" name="taskName[]" value="Task name">
  <input type="hidden" name="colors[]">
  <!--all same..-->
  <button>Add Status</button>
</div>
<div class='task'>
  <input type="text" name="taskName[]" value="Task name">
  <input type="hidden" name="colors[]">
  <!--all same..-->
  <button>Add Status</button>
</div> 

Then , inside your javascript code as you are iterating through your pill input you can add value of colors together in respective inputs i.e :

let colors = [];
let tasks = document.querySelectorAll('.task');
 for (let i = 0; i < tasks.length; i++) {
      //loop thrugh pill inside that div
      tasks[i].querySelectorAll('.pill').forEach(element => {
      colors.push(element.classList[1]);
  });
 tasks[i].querySelector("[name='colors[]']").value = colors //assign value to hiden input
   colors = [] //empty array
 }
   //other codes..ajax..call .

Quick demo :

let colors = [];
let tasks = document.querySelectorAll('.task');
for (let i = 0; i < tasks.length; i++) {
  //loop thrugh pill inside that div
  tasks[i].querySelectorAll('.pill').forEach(element => {
    colors.push(element.classList[1]);
  });
  tasks[i].querySelector("[name='colors[]']").value = colors
  colors = []
}
//other codes..ajax..etc
<form name="forms">
  <div class='task'>
    <input type="text" name="taskName[]" value="Task name">
    <!--for demo..change type="hidden"-->
    <input type="text" name="colors[]">
    <input type="text" name="status[]" class="pill gray" value="Status name">
    <input type="text" name="status[]" class="pill blue" value="Status Name">
    <input type="text" name="status[]" class="pill orange" value="Status Name">
    <button>Add Status</button>
  </div>
  <div class='task'>
    <input type="text" name="taskName[]" value="Task name">
    <input type="text" name="colors[]">
    <input type="text" name="status[]" class="pill red" value="Status name">
    <input type="text" name="status[]" class="pill yellow" value="Status Name">
    <button>Add Status</button>
  </div>
  <button>Add Task</button>
</form>

Lastly , in your backend page you can simply get that value using $_POST['colors'] and you can either explode it or display them directly via echo . i.e:

$taskName_array = isset($_POST['taskName']) ? $_POST['taskName'] : array();
$status = isset($_POST['colors']) ? $_POST['colors'] : array();
$total_rows = count($taskName_array);
for ($i = 0; $i < $total_rows; $i++) {
     echo $taskName_array[$i] ."\n";
     echo $status[$i];
}

While Swati's answer does technically work, I was getting an array that looked liked this

(
[0] => purple,gray,gray
[1] => 
[2] => 
[3] => red,gray,gray
[4] => 
[5] => 
)

I could go through and remove the empty array items but before Swati had posted an answer I was able to come up with a different way of bringing in the results

On the html, I changed the names to multidimensional arrays with keys

<form>
<div class='task'>
    <input type="text" name="task[][name]" value="Task name">            
    <input type="text" name="task[][status]" class="pill gray" value="Status name">
    <input type="text" name="task[][status]" class="pill blue" value="Status Name">
    <input type="text" name="task[][status]" class="pill orange" value="Status Name">
    <button>Add Status</button>
</div>
<div class='task'>
    <input type="text" name="task[][name]" value="Task name">            
    <input type="text" name="task[][status]" class="pill yellow" value="Status name">
    <input type="text" name="task[][status]" class="pill red" value="Status Name">
    <button>Add Status</button>
</div>
<button>Add Task</button>
</form>

The javascript remained unchanged. The php gets a bit wacky (Sorry for the lack of comments, I got parts of the code from somewhere else and I can't find that somewhere else):

$tasks_array = isset($_POST['task']) ? $_POST['task'] : array();
$colors_array = isset($_POST['colors']) ? $_POST['colors'] : array();
$colors_array = explode(',', $colors_array);
$keys = array_keys($tasks_array);
$count=0;

for($i = 0; $i < count($tasks_array); $i++) {
    foreach($tasks_array[$keys[$i]] as $key => $value) {
        if ($key == 'status') {
            // Status Name
            $statusName = $value;
            $colorName = $colors_array[$count];
            $count++;
        } else {
            $taskName = $value;
        }
    }
}

This will output

Taskname
  StatusName Color
  StatusName Color
  StatusName Color
Taskname
  StatusName Color
  StatusName Color

Their may be a better way of doing this but for now, I'm marking this as the accepted answer.

Related