2

Note: Issue has been resolved, partially. There's now an error in the loop to generate the <option> elements. More info at the bottom of this post. Bounty will still be rewarded to anyone who provides a solution for this new issue.

Note 2: Issue has been resolved, selected solution is for the error in the loop, I posted the solution of the origin question below for completeness.


I'm using Laravel 5.7 with laravelcollective/html for my forms.

I'm trying to create a page where the user can create an order and add products to it. The user has to be able to press a button with a + sign to add more products.

The regular number input for the quantity is easy, I can just append it using jQuery like this:

$(function() {
  $('#addMoreProducts').click(function(e) {
    e.preventDefault();
    $("#fieldList").append("<div class='col-sm-6'>");
    $("#fieldList").append("<div class='form-group'>");
    $("#fieldList").append("<label for='quantity[]'>Quantity</label>");
    $("#fieldList").append("<input class='form-control' placeholder='Quantity' name='quantity[]' type='number'>");
    $("#fieldList").append("</div>");
    $("#fieldList").append("</div>");
    $("#fieldList").append("</div>");
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

But I can not figure out how to add <select> inputs dynamically with the records from the database. These are the fields that I need to "duplicate".

<div class="row" id="fieldList">
   <div class="col-sm-6">
      <div class="form-group">
        {{Form::label('product_id[]', 'Product')}}
        {{Form::select('product_id[]', $products->pluck('name', 'id'), null, ['id' => 'select2', 'class' => 'form-control select2', 'placeholder' => 'Product'])}}
      </div>
    </div>
   <div class="col-sm-6">
     <div class="form-group">
       {{Form::label('quantity[]', 'Quantity')}}
       {{Form::number('quantity[]', '', ['class' => 'form-control', 'placeholder' => 'Quantity'])}}
     </div>
   </div>
</div>
    
<div class="form-group">
  <a id="addMoreProducts" class="btn btn-block btn-default">+</a>
</div>

Product info is passed in through the controller.

I've tried appending the <select> inputs as well and they display but ofcourse the options aren't in there.

$(function() {
  $('#addMoreProducts').click(function(e) {
    e.preventDefault();
    $("#fieldList").append("<div class='row' id='fieldlist'>");
    $("#fieldList").append("<div class='col-sm-6'>");
    $("#fieldList").append("<div class='form-group'>");
    $("#fieldList").append("<label for='product_id[]'>Product</label>");
    $("#fieldList").append("<select id='select2' class='form-control select2' name='product_id[]'><option selected='selected' value=''>Product</option></select>");
    $("#fieldList").append("</div>");
    $("#fieldList").append("</div>");
    $("#fieldList").append("<div class='col-sm-6'>");
    $("#fieldList").append("<div class='form-group'>");
    $("#fieldList").append("<label for='quantity[]'>Quantity</label>");
    $("#fieldList").append("<input class='form-control' placeholder='Quantity' name='quantity[]' type='number'>");
    $("#fieldList").append("</div>");
    $("#fieldList").append("</div>");
    $("#fieldList").append("</div>");
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

How do I add additional <select> inputs while keeping it populated by the rows in my database?

Not familiar with AJAX, but is this a scenario that I need it for? Any suggestions are greatly appreciated.

EDIT: This is the products table:

id|name|description|product_category_id|supplier_id|sales_price|buy_price|instock|discontinued

public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->mediumText('description');
        $table->integer('product_category_id')->unsigned();
        $table->integer('supplier_id')->unsigned();
        $table->decimal('sales_price', 8, 2);
        $table->decimal('buy_price', 8, 2);
        $table->boolean('instock');
        $table->boolean('discontinued');

        $table->foreign('product_category_id')->references('id')->on('product_categories')->onDelete('cascade');
        $table->foreign('supplier_id')->references('id')->on('suppliers')->onDelete('cascade');

        $table->timestamps();
    });
}

Example of what the generated <select> should look like:

<select id="select2" class="form-control select2" name="product_id[]">
  <option selected="selected" value="">Product</option>
  <option value="1">Windows 10 License</option>
  <!-- etc... -->
</select>

Partial solution:

I'm using this code to pass the $products variable so it's accesible by my js file:

<script>
  var products = {!! json_encode($products->toArray(), JSON_HEX_TAG) !!};
</script>

Tested this like so, with one product in the <select>:

/* Generate standard input */
input_select = `
    <div class="row">
        <div class="col-sm-6">
            <div class="form-group">
                <label for="product_id[]">Product</label>
                <select id="select2" class="form-control select2" name="product_id[]">
                <option selected="selected" value="">Product</option>
`;

/* generate options */
i = 0;
input_select += "               <option value='" + products[i].id + "'>" + products[i].name + "</option>";

/* Close standard input */
input_select += `
                </select>
            </div>
        </div>
        <div class="col-sm-6">
            <div class="form-group">
                <label for="quantity[]">Quantity</label>
                <input class="form-control" placeholder="Quantity" name="quantity[]" type="number" value="" id="quantity[]">
            </div>
        </div>
    </div>
`;

/* append function */
$(function() {
    $('#more').click(function(e) {
        e.preventDefault();
        $("#fieldlist").append(input_select);
        $('.select2').select2();
    });
});

This works fine and produces the desired result. But I need to loop the generate options part. I tried to do it like so:

for (var i = 0 < products.length; i++;) {
    input_select += "       <option value='" + products[i].id + "'>" + products[i].name + "</option>";
}

This throws the error:

TypeError: products[i] is undefined

This is what the products variable contains:

enter image description here

13
  • 2
    Hi, I can create an AJAX code to get this data from the database directly, but just include your database tables or records, to do that ;) Commented Jan 4, 2019 at 16:37
  • and add to your question, about any code if it's work - to know more about your problem :) Commented Jan 4, 2019 at 16:46
  • I added the migration. I would only need the name and ID and loop it so that it creates a <option> for each one. Commented Jan 4, 2019 at 16:53
  • Please tell me, what exactly should happen? Do you click a button, for example, a data set? Please explain more :) - for example an HTML code, you want to use it to show your data - I will create an AJAX but I don't know what will I send to Database and what will I receive for your page? Commented Jan 4, 2019 at 17:08
  • When I click the button, it should create the same inputs as in the post, below the last one, with the products in my database in the <select> Commented Jan 4, 2019 at 17:14

2 Answers 2

1
+50

I think the problem is on the for statement try this:

for (var i = 0; i < products.length; i++) {
    input_select += "       <option value='" + products[i].id + "'>" + products[i].name + "</option>";
}
Sign up to request clarification or add additional context in comments.

1 Comment

I feel stupid now haha. Thanks, this resolved the issue.
0

Just going to leave the total solution here, for anyone trying to accomplish the same / something similar.

You need to pass the data from your controller to your view and to your javascript file through a small script like this:

<script>
  // $products is passed in through the controller
  var products = {!! json_encode($products->toArray(), JSON_HEX_TAG) !!};
</script>

Then, create a javascript file and create a template literal for the input to be appended.

/* Generate standard input */
input_select = `
    <div class="row">
        <div class="col-sm-6">
            <div class="form-group">
                <label for="product_id[]">Product</label>
                <select id="select2" class="form-control select2" name="product_id[]">
                <option selected="selected" value="">Product</option>
`;

/* generate options */
for (var i = 0; i < products.length; i++) {
    input_select += "       <option value='" + products[i].id + "'>" + products[i].name + "</option>";
}

/* Close standard input */
input_select += `
                </select>
            </div>
        </div>
        <div class="col-sm-6">
            <div class="form-group">
                <label for="quantity[]">Quantity</label>
                <input class="form-control" placeholder="Quantity" name="quantity[]" type="number" value="" id="quantity[]">
            </div>
        </div>
    </div>
`;

/* append function */
$(function() {
    $('#more').click(function(e) {
        e.preventDefault();
        $("#fieldlist").append(input_select);

        /*
         *
         * Note: I use select2, if you don't, remove this line.
         *
         */
        $('.select2').select2();

    });
});

Then in your view, wrap the input that you'd like to append to in a div with the id of #fieldlist (or whatever you want, make sure to change it in the js file too)

<div id="fieldlist">

  <div class="row">
    <div class="col-sm-6">
      <div class="form-group">
        {{Form::label('product_id[]', 'Product')}}
        {{Form::select('product_id[]', $products->pluck('name', 'id'), null, ['id' => 'select2', 'class' => 'form-control select2', 'placeholder' => 'Product'])}}
      </div>
    </div>
    <div class="col-sm-6">
      <div class="form-group">
        {{Form::label('quantity[]', 'Quantity')}}
        {{Form::number('quantity[]', '', ['class' => 'form-control', 'placeholder' => 'Quantity'])}}
      </div>
    </div>
  </div>

</div>

Finally, for the button:

<div class="form-group">
  <a id="more" class="btn btn-block btn-default">+</a>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.