skip to Main Content

I have a form setup like this:

<form action="/clients/{{ $client->id }}/create-invoice" method="post">
    <div class="form-group">
        <label for="due_date" class="sr-only">Due Date</label>
        <input type="date" name="due_date" class="form-control" placeholder="Due Date">
    </div>
    <hr />
    <p class="clearfix">
        <strong class="pull-left">Invoice Items</strong>
        <a id="add_invoice_item" class="pull-right"><span class="fa fa-plus"></span></a>
    </p>
    <div class="form-group invoice_item">
        <div class="row">
            <div class="col-ms-6 col-sm-8">
                <input type="text" name="item_description[]" class="form-control" placeholder="Description">
            </div>
            <div class="col-ms-3 col-sm-2">
                <input type="number" class="form-control" name="item_quantity[]" placeholder="Quantity">
            </div>
            <div class="col-ms-3 col-sm-2">
                <input type="text" class="form-control" name="item_price[]" placeholder="Price">
            </div>
        </div>
    </div>
    <div class="form-group">
        <input type="hidden" name="_token" value={{ csrf_token() }}>
        <button class="btn-primary btn btn-block">Create Invoice</button>
    </div>
</form>

I am using Laravel 5.2.

I have the following jQuery to allow the user to add more invoice items:

$("#add_invoice_item").click(function(){
    $(".invoice_item").first().clone().insertAfter("div.invoice_item:last").find("input[type='text']").val("");
});

The problem is when I am looking at the request:

public function store(Request $request, Client $client)
{
    return $request->all();
}

It returns this:

{
  "due_date": "2016-11-19",
  "item_description": [
    "Website Development",
    "SEO",
    "Server Setup"
  ],
  "item_quantity": [
    "1",
    "1",
    "1"
  ],
  "item_price": [
    "450.00",
    "300.00",
    "100.00"
  ],
  "_token": "7tUMdXX9FBU4a7cug51oBlrRyeBi9H8ucUNltQgM"
}

And whilst that is the expected result I am not sure how to get it to return in a way which it is easy to use.

For example I need instead of 3 different array lists I need one array list with each object with each field for that row object.

So:

That it would be returning this:

{
  "due_date": "2016-11-19",
  "items": [
    {"description": "Server Setup", "price": "100.00", "quantity": "1"},
    {"description": "SEO", "price": "300.00", "quantity": "1"},
    {"description": "Website Development", "price": "450.00", "quantity": "1"}
  ],
  "_token": "7tUMdXX9FBU4a7cug51oBlrRyeBi9H8ucUNltQgM"
}

I assume I need to change the HTML and the jQuery but I am unsure how to get it working so that jQuery adds the new fields properly and into the array of items

Thanks!

2

Answers


  1. Change naming of your array to product[i][field]

    <input type="text" name="product[0][description]"/>
    <input type="text" name="product[0][quantity]"/>
    <input type="text" name="product[0][price]"/>
    
    <input type="text" name="product[1][description]"/>
    <input type="text" name="product[1][quantity]"/>
    <input type="text" name="product[1][price]"/>
    

    And in PHP you will receive this:

    var_dump($_POST['product']);
    
    [
        [
            'description': 'Website development',
            'quantity': '1',
            'price': '450.00'
        ],
        [
            'description': 'SEO',
            'quantity': '1',
            'price': '300.00'
        ],
    ]
    

    Only disadvantage is that you need to manually set array index.


    Using jQuery and template:

    var index = 0;
    
    function add() {
      $('.form').append(template('#my-template', {
        i: index
      }));
      index++;
    }
    
    function template(selector, params) {
      if (typeof params === 'undefined') {
        params = [];
      }
    
      var tplEl = $(selector);
    
      if (tplEl.length) {
        var tpl = $(selector).html();
    
        $.each(params, function(i, n) {
          tpl = tpl.replace(new RegExp("\{" + i + "\}", "g"), function() {
            if (typeof n === 'object') {
              return n.get(0).outerHTML;
            } else {
              return n;
            }
          });
        });
    
        return $(tpl);
      } else {
        console.error('Template "' + selector + '" not found!');
      }
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <button onClick="add()">Add more</button>
    <hr/>
    <div class="form">
    
    </div>
    <script type="text/jQuery-tpl" id="my-template">
      <div class="row">
        {i}: 
        <input type="text" name="product[{i}][description]" />
        <input type="text" name="product[{i}][quantity]" />
        <input type="text" name="product[{i}][price]" />
      </div>
    </script>
    Login or Signup to reply.
  2. Ah, it has to be done in jQuery. Well, it’s also quite easy. Do something like this:

    $('.invoice_item').each(function(i, el) {
        // i holds the index. Use it to alter the checkboxes
        $(this)
            .find('input[name="item_description[]"]')
            .attr('name', 'item_description[' + i + ']');
    
        // Do the same for price and quantity
    });
    

    When you post the form, the item properties will be grouped by each row.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search