Home > Back-end >  Node.js cannot access response attribute when collecting form data without input tags
Node.js cannot access response attribute when collecting form data without input tags

Time:12-31

I am trying to collect form data with Node.js but I am unable to retrieve it.

I have the following add_device.html page:

<head>
    <script>
        /* Submit device type form when user clicks on div */
        $(function () {
            $(".device-form").on("click", function () {
                alert(this.device.value);
                $(".device-form").submit();
            });

        });
    </script>
</head>

<body>
    <div id="devices-available-container">

        <% deviceTypes.forEach(function(deviceType){ %>
        <div >
            <form  method="POST" action="/add_device">
                <div >
                    <div ><img  src="/img/device_types/<%=deviceType.device%>.png"
                            alt="Lightbulb icon"></div>
                    <div >
                        <button name="device" value="<%= deviceType.device %>"
                            type="text"><%= deviceType.device %></button>
                    </div>
                </div>
            </form>
        </div>
        <% }) %>

    </div>
</body>

and in main.js (routes):

app.get("/add_device", function (req, res) {
        // query database to get all the books
        let sqlquery = "SELECT * FROM available_devices GROUP BY device order by device;";
        // execute sql query
        db.query(sqlquery, (err, result) => {
            if (err) {
                console.log(err);
                console.log(result);
                res.redirect("/");
            }
            //res.send(result)
            console.log(result);
            res.render("add_device.html", { deviceTypes: result });
        });
    });

    app.post('/add_device', function (req, res) {


        console.log(req.body.device);
        
    });

The rendered HTML is a series of items in a list. When the user clicks on a div containing the item icon and name (yellow box in the image), I want the 'form' to be submitted with the 'device' attribute set to the name of the item clicked.

enter image description here

For example, if the user clicks within the div containing bathtub, the form should be posted and from main.js, req.body.device should equal 'bathtub'.

However, for some reason, the result of console.log(req.body.device); is:

<ref *2> ServerResponse {
  _events: [Object: null prototype] { finish: [Function: bound resOnFinish] },
  _eventsCount: 1,
  _maxListeners: undefined,
  outputData: [],
  outputSize: 0,
  writable: true,
  destroyed: false,
  _last: false,
  chunkedEncoding: false,
  shouldKeepAlive: true,
  _defaultKeepAlive: true,
  useChunkedEncodingByDefault: true,
  sendDate: true,
  _removedConnection: false,
  _removedContLen: false,
  _removedTE: false,
  _contentLength: null,
  _hasBody: true,
  _trailer: '',
  finished: false,
  _headerSent: false,
  socket: <ref *1> Socket {
    connecting: false,
    _hadError: false,
    _parent: null,
    _host: null,
    _readableState: ReadableState {
      objectMode: false,
      highWaterMark: 16384,
      buffer: BufferList { head: null, tail: null, length: 0 },
      length: 0,
      pipes: [],
      flowing: true,
      ended: false,
      endEmitted: false,
      reading: true,
      sync: false,
      needReadable: true,
      emittedReadable: false,
      readableListening: false,
      resumeScheduled: false,
      errorEmitted: false,
      emitClose: false,
      autoDestroy: false,
      destroyed: false,
      errored: null,
      closed: false,
      closeEmitted: false,
      defaultEncoding: 'utf8',
      awaitDrainWriters: null,
      multiAwaitDrain: false,
      readingMore: false,
      decoder: null,
      encoding: null,
      [Symbol(kPaused)]: false
    },
    _events: [Object: null prototype] {
      end: [Array],
      timeout: [Function: socketOnTimeout],
      data: [Function: bound socketOnData],
      error: [Function: socketOnError],
      close: [Array],
      drain: [Function: bound socketOnDrain],
      resume: [Function: onSocketResume],
      pause: [Function: onSocketPause]
    },
    _eventsCount: 8,
    _maxListeners: undefined,
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: false,
      needDrain: false,
      ending: false,
      ended: false,
      finished: false,
      destroyed: false,
      decodeStrings: false,
      defaultEncoding: 'utf8',
      length: 0,
      writing: false,
      corked: 0,
      sync: true,
      bufferProcessing: false,
      onwrite: [Function: bound onwrite],
      writecb: null,
      writelen: 0,
      afterWriteTickInfo: null,
      buffered: [],
      bufferedIndex: 0,
      allBuffers: true,
      allNoop: true,
      pendingcb: 0,
      prefinished: false,
      errorEmitted: false,
      emitClose: false,
      autoDestroy: false,
      errored: null,
      closed: false,
      closeEmitted: false
    },
    allowHalfOpen: true,
    _sockname: null,
    _pendingData: null,
    _pendingEncoding: '',
    server: Server {
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      _connections: 1,
      _handle: [TCP],
      _usingWorkers: false,
      _workers: [],
      _unref: false,
      allowHalfOpen: true,
      pauseOnConnect: false,
      httpAllowHalfOpen: false,
      timeout: 0,
      keepAliveTimeout: 5000,
      maxHeadersCount: null,
      headersTimeout: 60000,
      requestTimeout: 0,
      _connectionKey: '6::::8089',
      [Symbol(IncomingMessage)]: [Function: IncomingMessage],
      [Symbol(ServerResponse)]: [Function: ServerResponse],
      [Symbol(kCapture)]: false,
      [Symbol(async_id_symbol)]: 12
    },
    _server: Server {
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      _connections: 1,
      _handle: [TCP],
      _usingWorkers: false,
      _workers: [],
      _unref: false,
      allowHalfOpen: true,
      pauseOnConnect: false,
      httpAllowHalfOpen: false,
      timeout: 0,
      keepAliveTimeout: 5000,
      maxHeadersCount: null,
      headersTimeout: 60000,
      requestTimeout: 0,
      _connectionKey: '6::::8089',
      [Symbol(IncomingMessage)]: [Function: IncomingMessage],
      [Symbol(ServerResponse)]: [Function: ServerResponse],
      [Symbol(kCapture)]: false,
      [Symbol(async_id_symbol)]: 12
    },
    parser: HTTPParser {
      '0': [Function: bound setRequestTimeout],
      '1': [Function: parserOnHeaders],
      '2': [Function: parserOnHeadersComplete],
      '3': [Function: parserOnBody],
      '4': [Function: parserOnMessageComplete],
      '5': [Function: bound onParserExecute],
      '6': [Function: bound onParserTimeout],
      _headers: [],
      _url: '',
      socket: [Circular *1],
      incoming: [IncomingMessage],
      outgoing: null,
      maxHeaderPairs: 2000,
      _consumed: true,
      onIncoming: [Function: bound parserOnIncoming],
      [Symbol(resource_symbol)]: [HTTPServerAsyncResource]
    },
    on: [Function: socketListenerWrap],
    addListener: [Function: socketListenerWrap],
    prependListener: [Function: socketListenerWrap],
    _paused: false,
    _httpMessage: [Circular *2],
    [Symbol(async_id_symbol)]: 15351,
    [Symbol(kHandle)]: TCP {
      reading: true,
      onconnection: null,
      _consumed: true,
      [Symbol(owner_symbol)]: [Circular *1]
    },
    [Symbol(kSetNoDelay)]: false,
    [Symbol(lastWriteQueueSize)]: 0,
    [Symbol(timeout)]: null,
    [Symbol(kBuffer)]: null,
    [Symbol(kBufferCb)]: null,
    [Symbol(kBufferGen)]: null,
    [Symbol(kCapture)]: false,
    [Symbol(kBytesRead)]: 0,
    [Symbol(kBytesWritten)]: 0,
    [Symbol(RequestTimeout)]: undefined
  },
  _header: null,
  _keepAliveTimeout: 5000,
  _onPendingData: [Function: bound updateOutgoingData],
  _sent100: false,
  _expect_continue: false,
  req: IncomingMessage {
    _readableState: ReadableState {
      objectMode: false,
      highWaterMark: 16384,
      buffer: BufferList { head: null, tail: null, length: 0 },
      length: 0,
      pipes: [],
      flowing: true,
      ended: true,
      endEmitted: true,
      reading: false,
      sync: true,
      needReadable: false,
      emittedReadable: false,
      readableListening: false,
      resumeScheduled: false,
      errorEmitted: false,
      emitClose: true,
      autoDestroy: false,
      destroyed: false,
      errored: null,
      closed: false,
      closeEmitted: false,
      defaultEncoding: 'utf8',
      awaitDrainWriters: null,
      multiAwaitDrain: false,
      readingMore: true,
      decoder: null,
      encoding: null,
      [Symbol(kPaused)]: false
    },
    _events: [Object: null prototype] { end: [Function: clearRequestTimeout] },
    _eventsCount: 1,
    _maxListeners: undefined,
    socket: <ref *1> Socket {
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: null,
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 8,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: [Server],
      _server: [Server],
      parser: [HTTPParser],
      on: [Function: socketListenerWrap],
      addListener: [Function: socketListenerWrap],
      prependListener: [Function: socketListenerWrap],
      _paused: false,
      _httpMessage: [Circular *2],
      [Symbol(async_id_symbol)]: 15351,
      [Symbol(kHandle)]: [TCP],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(RequestTimeout)]: undefined
    },
    httpVersionMajor: 1,
    httpVersionMinor: 1,
    httpVersion: '1.1',
    complete: true,
    headers: {
      host: 'localhost:8089',
      connection: 'keep-alive',
      'content-length': '0',
      'cache-control': 'max-age=0',
      'upgrade-insecure-requests': '1',
      origin: 'http://localhost:8089',
      'content-type': 'application/x-www-form-urlencoded',
      'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/88.0.4324.150 Safari/537.36',
      accept: 'text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
      'sec-fetch-site': 'same-origin',
      'sec-fetch-mode': 'navigate',
      'sec-fetch-user': '?1',
      'sec-fetch-dest': 'document',
      referer: 'http://localhost:8089/add_device',
      'accept-encoding': 'gzip, deflate, br',
      'accept-language': 'en-US'
    },
    rawHeaders: [
      'Host',
      'localhost:8089',
      'Connection',
      'keep-alive',
      'Content-Length',
      '0',
      'Cache-Control',
      'max-age=0',
      'Upgrade-Insecure-Requests',
      '1',
      'Origin',
      'http://localhost:8089',
      'Content-Type',
      'application/x-www-form-urlencoded',
      'User-Agent',
      'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/88.0.4324.150 Safari/537.36',
      'Accept',
      'text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
      'Sec-Fetch-Site',
      'same-origin',
      'Sec-Fetch-Mode',
      'navigate',
      'Sec-Fetch-User',
      '?1',
      'Sec-Fetch-Dest',
      'document',
      'Referer',
      'http://localhost:8089/add_device',
      'Accept-Encoding',
      'gzip, deflate, br',
      'Accept-Language',
      'en-US'
    ],
    trailers: {},
    rawTrailers: [],
    aborted: false,
    upgrade: false,
    url: '/add_device',
    method: 'POST',
    statusCode: null,
    statusMessage: null,
    client: <ref *1> Socket {
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: null,
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 8,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: [Server],
      _server: [Server],
      parser: [HTTPParser],
      on: [Function: socketListenerWrap],
      addListener: [Function: socketListenerWrap],
      prependListener: [Function: socketListenerWrap],
      _paused: false,
      _httpMessage: [Circular *2],
      [Symbol(async_id_symbol)]: 15351,
      [Symbol(kHandle)]: [TCP],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(RequestTimeout)]: undefined
    },
    _consuming: false,
    _dumped: false,
    next: [Function: next],
    baseUrl: '',
    originalUrl: '/add_device',
    _parsedUrl: Url {
      protocol: null,
      slashes: null,
      auth: null,
      host: null,
      port: null,
      hostname: null,
      hash: null,
      search: null,
      query: null,
      pathname: '/add_device',
      path: '/add_device',
      href: '/add_device',
      _raw: '/add_device'
    },
    params: {},
    query: {},
    res: [Circular *2],
    body: {},
    _body: true,
    length: undefined,
    route: Route { path: '/add_device', stack: [Array], methods: [Object] },
    [Symbol(kCapture)]: false,
    [Symbol(RequestTimeout)]: undefined
  },
  locals: [Object: null prototype] {},
  [Symbol(kCapture)]: false,
  [Symbol(kNeedDrain)]: false,
  [Symbol(corked)]: 0,
  [Symbol(kOutHeaders)]: [Object: null prototype] {
    'x-powered-by': [ 'X-Powered-By', 'Express' ]
  }
}

What I would like to have when printing console.log(req.body.device); is something like { device: dviceNameClickedByTheUser } Any help would be much appreciated, thanks!

CodePudding user response:

Make sure you are using express.urlencoded({ extended: true }) middleware, as shown in the documentation otherwise req.body will be undefined.

The output of console.log(req.body.device) you posted is probably the result of outdated code running, because that is what you would normally get from running console.log(req). I've tried running your code and the console output works correctly https://www.anyfiddle.com/p/robalb/sih511dv

Also this is not relevant to the question, but you can get rid of the javascript code in your template by changing the type of the form button from type="text" to type="submit" like this

<button name="device" value="<%= deviceType.device %>"
                            type="submit"><%= deviceType.device %></button>

CodePudding user response:

Resolved by using hidden input tag:

<script>
    /* Submit device type form when user clicks on div */
    $(function () {
        $(".device-form").on("click", function () {
            $(this).submit();
        });

    });
</script>

<body>
    <div id="devices-available-container">

        <% deviceTypes.forEach(function(deviceType){ %>
        <div >
            <form  method="POST" action="/add_device">
                <input input type="hidden" id="first" type="text" name="device" value="<%= deviceType.device %>" />
                <div >
                    <div ><img  src="/img/device_types/<%=deviceType.device%>.png"
                            alt="Lightbulb icon"></div>
                    <div >
                        <p><%= deviceType.device %></p>
                    </div>
                </div>
            </form>
        </div>
        <% }) %>

    </div>
</body>
  • Related