0

I have written some JavaScript below. It's very simple and adds an event to a button found by it's class. When I click the button, however, nothing happens.

Please can anyone help as I have been trouble shooting this for a while and I just cannot get it.

@extends('layouts.app')

@section('content')

 <h1>Create new</h1>

{{--  Purchase order --}}
 {{ Form::open(['route' => 'po.store']) }}

    {{ Form::label('supplier', 'Supplier') }}
    {{ Form::select('supplier', [$suppliers], null, ['placeholder' => 'Select a supplier...']) }}
    {{ Form::label('staff', 'Staff') }}
    {{ Form::select('staff', [$staff], null, ['placeholder' => 'Select a staff member']) }}
    {{ Form::label('status', 'Status' ) }}
    {{ Form::select('status', [$statuses]) }}
    <br>
    {{ Form::label('deliverto', 'Deliver To:') }}
    {{ Form::text('deliverto', '') }}
    <br>
    {{ Form::label('priceex', 'Price (ex VAT)') }}
    {{ Form::text('priceex') }}
    {{ Form::label('priceinc', 'Price (inc VAT)') }}
    {{ Form::text('priceinc') }}
    {{ Form::submit('Submit') }}

<hr>

{{-- Lines section--}}

 <table id="linesTable">
    <tr> {{--headings--}}
        <th>Code</th>
        <th>Quantity</th>
        <th>Description</th>
        <th>Price (ex VAT)</th>
        <th>Price (inc VAT)</th>
        <th>notes</th>
        <th></th>
    </tr>
     <tr>
         <td>{{Form::text("lines[0][code]")}}</td>
         <td>{{Form::text("lines[0][quantity]")}}</td>
         <td>{{Form::text("lines[0][description]")}}</td>
         <td>{{Form::text("lines[0][price_ex_vat]", null, ["class" => "textbox_prices"])}}</td>
         <td>{{Form::text("lines[0][price_inc_vat]", null, ["class" => "textbox_prices"])}}</td>
         <td>{{Form::text("lines[0][notes]")}}</td>
         <td><button type="button">Remove</button></td>

 </table>
 <button type="Button" id="addNew">Add New Line</button>

 {{ Form::close()}}

    <script type="text/javascript">
        document.getElementById("addNew").addEventListener("click", insertRow);
        function insertRow() {
            alert('hi');
        }

    </script>
@endsection
gclark18
  • 659
  • 6
  • 23
  • 1
    is there an error in the console? – epascarello Jul 11 '19 at 14:35
  • works in fiddle: https://jsfiddle.net/10rkn7ut/ I think you have another error – Robb Jul 11 '19 at 14:41
  • One problem that I can see is that you never close the second ``. – Lewis Jul 11 '19 at 14:42
  • 2
    What folks are asking for above is a [mcve], see the link for details. Note that we don't need to see the template, we need to see what the browser sees, the actual HTML. – T.J. Crowder Jul 11 '19 at 14:43
  • Try to wrap it inside a window.onload event, like this : `window.onload=function() {add your event listener here}`. DOM may not be loaded when you add your eventListener, so your element doesn’t exist yet and that’s why it may happen – KawaLo Jul 11 '19 at 14:44
  • 1
    @Lewis - It's [optional](https://html.spec.whatwg.org/#optional-tags) (but since they provided the other one, consistency would be good). – T.J. Crowder Jul 11 '19 at 14:44
  • 1
    @T.J.Crowder *Mind Blown* – Lewis Jul 11 '19 at 14:45
  • 1
    @KawaLo - 1. Unless the templating system reorganizes things, the call to get the element is clearly *after* the element. 2. If it weren't, `load` is not the right place to hook it up, it's far too late in the process (waits for all images, etc.). Instead, ensure the script is at the end of the HTML, or use `defer`, or use a module, or use the `DOMContentLoaded` event. – T.J. Crowder Jul 11 '19 at 14:45
  • 1
    @KawaLo That worked, thank you. – gclark18 Jul 11 '19 at 14:56
  • @T.J.Crowder should I used DOMContentLoaded event rather than window.onload? I have tried to ensure my script is at the end of the file but it just doesnt want to work. `DOMContentLoaded` & `window.onload=function() {}` work – gclark18 Jul 11 '19 at 15:06
  • @GlenUK - I would use `DOMContentLoaded` rather than `window.onload` **or** add `defer` to your `script` tag (unless you need to support IE < 10), [more here](https://html.spec.whatwg.org/multipage/scripting.html#attr-script-defer). – T.J. Crowder Jul 11 '19 at 15:25

2 Answers2

3

I post here the comment that was accepted. I’m not sure about the technical details, but a good practice to deal with DOM parsing is to always ensure the document is fully loaded, before doing anything.

Here is an example of what to do :

window.addEventListener(‘DOMContentLoaded’, () => {
  // Add your event listeners here
  // Also better practice, declare your function before appending the listener
  function insertRow() {
    alert('hi');
  }
  document.getElementById("addNew").addEventListener("click", insertRow);
});

Two edits to my comment :

  • First, window.onload isn’t the best way to deal with event. It is better to go with an eventListener attached to the window object
  • Second, as mentioned in @T.J.Crowder answer, the load event waits for the full page to charge, including images and other stuff. Instead, prefer the DOMContentLoadedevent, which will be emitted once the DOM is ready (but not waiting for all side stuff to load). Here is a look at the documentation : MDN - Doc

It is also not quite a good practice to add javascript code directly inside HTML. Prefer using external script, which you load at the end of your HTML, just before (or after) the </body> closure tag, like this :

<script src=‘path_to_my_script/script.js’></script> 

Hope it solve everything !

KawaLo
  • 1,783
  • 3
  • 16
  • 34
0

The way JavaScript works you are trying to set the event listener before the button is created. Two solutions:

 window.addEventListener('DOMContentLoaded', (event) => {
   contentLoaded();
 });
 function contentLoaded()
 {
    document.getElementById("addNew").addEventListener("click", insertRow);
 }

Or you can do it with HTML:

 <body onload="contentLoaded()">
Cyberboy1551
  • 345
  • 1
  • 13