1

I have this select-box I just add it via jQuery:

<span onclick="createProduct()">Add New<i class="fa fa-plus"></i></span>

<script>

function createProduct() {
        var html = '';
        html += '   <div class="col-xs-12">';
        html += '      <div class="form-group">';
        html += '          <div class="input-group">';
        html += '               <span class="input-group-addon input-group-addon-small"><i class="sicon-tag-special"></i></span>';
        html += '               <select class="form-control" name="category_id" style="width: 100%">';
        html += '                  <option value="">Select Category.. </option>';
        html += '                  <option value="">Category1</option>';
        html += '                  <option value="">Category2</option>';
        html += '               </select>';
        html += '          </div>';
        html += '       </div>';
        html += '    </div>';

     $('#products_div').prepend(html);
 }

</script>

Here when the Admin clicks on the add new button, a select element is added in the page. My problem is with creating the the options in the select element. I have this foreach I need to put it into this js code!

@foreach($categories as $category)
    <option value="{{ $$category->id }}">{{ $category->name }}</option>
@endforeach
Wasbeer
  • 389
  • 2
  • 11
  • By the way, you can use ` ` for multiline strings. concatenating each line programatically is not good for performance. – t.m. Jan 26 '20 at 16:45
  • @t.m. Ohh! Can you pls give me an example for that? –  Jan 26 '20 at 16:49
  • 1
    Note that template literals (ie. ` `) doesn't work at all in IE and concatenating strings is more of a code-ugliness issue than a performance one. Concatenating a string takes less than 3ms. – Rory McCrossan Jan 26 '20 at 16:50
  • @RoryMcCrossan it's ok with IE, because my project just will be admin-panel and api there is front-end –  Jan 26 '20 at 16:52
  • 1
    See this post https://stackoverflow.com/questions/805107/creating-multiline-strings-in-javascript – t.m. Jan 26 '20 at 16:52
  • @RoryMcCrossan I agree that it is not a big deal most of the time, but it might be noticable if this function gets called too frequently or string get bigger. And it is ugly :) – t.m. Jan 26 '20 at 16:55
  • No arguments there :) – Rory McCrossan Jan 26 '20 at 16:55
  • There are multiple ways to do this but I imagine the most straightforward one is to simply put the laravel `@foreach` loop inside the JS function and add `html += ` inside the loop? Mixing code like that is ugly, but I'm mostly wondering whether you've tried this, and if not, why not? –  Jan 26 '20 at 16:57
  • @t.m. thank you I didn't know about this ` ` one before! it's great. And thank all of whose suggestion something :) –  Jan 26 '20 at 17:10

2 Answers2

2

In this case, as the HTML you want to append is governed by the content coming from your Laravel back end, it would make far more sense to de-couple the HTML and the JS. As such, create the HTML in the DOM when the page loads and hide it. Then in the JS you can clone that HTML and append it where it is required to be displayed. Something like this:

$('.add-new-product').on('click', function() {
  var $clone = $('#new-product-content > div').clone();
  $clone.appendTo('#products-div');
});
#new-product-content {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="add-new-product">Add New<i class="fa fa-plus"></i></span>
<div id="products-div"></div>

<div id="new-product-content">
  <div class="col-xs-12">
    <div class="form-group">
      <div class="input-group">
        <span class="input-group-addon input-group-addon-small"><i class="sicon-tag-special"></i></span>
        <select class="form-control" name="category_id" style="width: 100%">
          <option value="">Select Category...</option>
          <!-- 
          output your categories here, eg.
          @foreach($categories as $category)
            <option value="{{ $$category->id }}">{{ $category->name }}</option>
          @endforeach
        
          Below is just for demo purposes... -->
          <option value="lorem">Lorem</option>
          <option value="ipsum">Ipsum</option>
          <option value="dolor">Dolor</option>
          <option value="sit">Sit</option>
        </select>
      </div>
    </div>
  </div>
</div>

Also note the use of unobtrusive event handlers here. Using inline event handlers in your HTML, such as onclick etc., is bad practice and should be avoided where possible.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • Sir, can you pls put delete button for each select box that If I need to delete it after added for example ? –  Jan 26 '20 at 21:03
1

You could do something like this:

function createProduct() {
  // Echo the JSON for the options in your JS
  var options =  @json($categories);
  // Map options to their HTML version, and join them
  var optionsHtml = options.map(function (opt) {
    return '<option value="' + opt.id + '">' + opt.name + '</option>';
  }).join('');

  var html = '   <div class="col-xs-12">'
           + '      <div class="form-group">'
           + '          <div class="input-group">'
           + '               <span class="input-group-addon input-group-addon-small"><i class="sicon-tag-special"></i></span>'
           + '               <select class="form-control" name="category_id" style="width: 100%">'
           + '                  <option value="">Select Category.. </option>'
           +                    optionsHtml // Add them here
           + '               </select>'
           + '          </div>'
           + '       </div>'
           + '    </div>';

     $('#products_div').prepend(html);
 }
blex
  • 24,941
  • 5
  • 39
  • 72
  • Then now I need in controller to send the data of categories like json ? –  Jan 26 '20 at 16:54
  • You don't _need_ to. It's just a suggestion of one possible way. If Rory's way suits you better, then go for it :) – blex Jan 26 '20 at 16:58