Jquery hide or show text field based on radio button selection

I have the following code to display text box based on radio button selection. This does not work however. How to make this code work?

I want the text box field to show if useDockerCompose is chosen to Yes and hide if the selection is no.

<tr><td>
                <b>Docker Compose</b>
                <a href="#" id="dcPop" rel="popover" data-content="Application deploys set to use docker compose to spin up the container" data-original-title="Use Docker Compose"><i class="icon-question-sign"></i></a>
            </td><td>               
                <input type="radio" value="false" name="useDockerCompose" CHECKED> No &nbsp;
                <input type="radio" value="true" name="useDockerCompose"> Yes
            </td></tr>          
            <tr class="dccommandtext" style="display:none;">
                <td nowrap><b>Docker Compose Command</b></td>
                <td><input type="text" class="input-xxlarge" name="dccommand"></td>
            </tr>
      
      <script src="https://code.jquery.com/jquery-3.6.0.min.js"/>
    <script type="text/javascript">
        
        
        $(document).ready(function() {
                // Function to show/hide the Docker Compose Command input based on the selected radio button
                function showdccommand() {
                    var selectedValue = $('input[name="useDockerCompose"]:checked').val();
                    console.log("Selected value: " + selectedValue);  // For debugging

                    if (selectedValue === "false") {
                        $('.dccommandtext').hide();
                    } else {
                        $('.dccommandtext').show();
                    }
                }

                // Attach the 'change' event listener to the radio buttons
                $('input[name="useDockerCompose"]').on('change', showdccommand);

                // Trigger show/hide on page load to set the initial state based on the default selected value
                showdccommand();
                });
            
    </script>

How can I reuse a function in NiceGUI slots without client-side code duplication?

NiceGUI documentation on conditional formatting in Table suggests the following:

table.add_slot('body-cell-age', '''
    <q-td key="age" :props="props">
        <q-badge :color="props.value < 21 ? 'red' : 'green'">
            {{ props.value }}
        </q-badge>
    </q-td>
''')

This has a very simple logic, namely props.value < 21 ? 'red' : 'green'

I do want to put way more advanced formatting logic here, and reuse it across the entire app – in many slots of many different components. I do not want to just inline the same code snippet for each slot as this will result in a lot of extra code duplication on the client side. Instead, I want to define a function once, and call it from each slot.

How can I do it?

I tried attaching a function to window by adding <script> with ui.add_head_html but it was not recognized in my slot.

I tried using custom VUE component for my slot definition but then it doesn’t appear to populate props.

Why does the in operator return false for a Proxy property, but the property is still accessible in JavaScript?

I’m trying to use a JavaScript Proxy to hide a property from detection while keeping it in the target object. The has trap successfully makes 'secret' in proxy return false, but the property is still accessible directly.

Code Example:

const target = { secret: 123, public: 456 };
const proxy = new Proxy(target, {
  has(t, prop) {
    if (prop === 'secret') return false; // Hide from `in` checks
    return prop in t;
  }
});

console.log('secret' in proxy); 
console.log(proxy.secret);      

Questions:

  1. Why does the in operator not block direct access to the property?
  2. How can I fully hide a property in a Proxy so it’s undetectable and inaccessible?
  3. Are there specific traps (e.g., get, ownKeys) that must be implemented together for consistency?

Observed Behavior:

  • 'secret' in proxy correctly returns false.
  • proxy.secret still returns the value 123.

Expected Behavior:
If the in operator returns false for 'secret', accessing proxy.secret should throw an error or return undefined.

Attempts to Fix:

  1. Tried using only the has trap.
  2. Researched other traps like get and ownKeys but unsure how to coordinate them.

How to use module imports in my main content script [duplicate]

I’m building a Chrome extension and getting this error when trying to use ES6 modules in my content script:

Uncaught SyntaxError: Cannot use import statement outside a module

Here’s my current setup:

manifest.json:

{
  "manifest_version": 3,
  "name": "MyExtension",
  "version": "1.0",
  "permissions": ["scripting", "activeTab"],
  "host_permissions": ["<all_urls>"],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html"
  }
}

content.js:

import {
    createMainSection,
    createMessageInput,
    createNavBar,
    createRightContainer,
    createSendButton,
    createToolBar,
    createToolBarButton,
} from "./utils.js";
import ElementSelector from "./element_selector.js";
import SelectorMenu from "./selector_menu.js";
import MessageList from "./message_list.js";

// Rest of content script code...

The content script is injected via background.js:

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    if (changeInfo.status === "complete" && /^https?:/.test(tab.url)) {
        chrome.scripting.executeScript({
            target: {tabId: tabId},
            files: ["content.js"],
        });
    }
});

I’m trying to modularize my code using ES6 modules, but getting the error above. How can I properly use ES6 modules in a Chrome extension content script?

JavaScript and PHP report different character counts when a newline is included. How do I make them agree? [duplicate]

I’ve made a web tool that lets me send SMS messages through my SIP provider’s API.

But there seems to be a discrepancy between character counts in PHP and JavaScript.

I have a javascript function that counts the characters in a textarea where I type the SMS message, using a simple varName.length call. If I hit the Enter key while typing in that textarea, it adds a newline character, and the character-counter function correctly increments the character count by 1 char.

So far so good!

BUT

Sending the SMS message happens through PHP, and if the full message is longer than 160 chars I have to break it up into multiple 160-char partial messages.

The problem is PHP’s strlen() function seems to calculate those newlines as having 2-characters each.

So for example, let’s say I type a message that has exactly 160 characters, and it includes, say, 5 newlines.

The javascript function will display the total character count as 160, so it seems like that message should send just fine. But PHP’s strlen() thinks the character count is 165, so it splits the message into two, pushing the last 5 characters into a separate message.

How can I reconcile this so that PHP and JavaScript both report the same number of characters when a message includes newlines?

Failed to resolve import “UseDebounce” from “src/SearchComponent.jsx”. Does the file exist?

I’m following this tutorial on Medium for using a debounce with autocomplete in React.
https://medium.com/@sankalpa115/usedebounce-hook-in-react-2c71f02ff8d8
But nothing is rendering and I’m receiving this error:

Failed to resolve import “UseDebounce” from “src/SearchComponent.jsx”.
Does the file exist?

I’m using node -v v23.7.0, npm -v 10.9.2 and Vite
I’ve tried adding <base href="./src"> to my index.html with no results.

main.js

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'    
createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

App.js

import React from 'react';
import Button from '@mui/material/Button';
import FirstComponent from './FirstComponent';
import SearchComponent from './SearchComponent';

function App() {
  
  return (
    <>
      <Button variant='contained'>Login</Button>
      <SearchComponent />
    </>
  )
}
export default App

UseDebounce.jsx

import { useState, useEffect } from 'react';    
function UseDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);    
  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
}    
export default UseDebounce;

SearchComponent.jsx

import React, { useState } from 'react';
import UseDebounce from 'UseDebounce';

function SearchComponent() {
  const [searchTerm, setSearchTerm] = useState('');
  const [searchResults, setSearchResults] = useState([]);
  
  // Set delay time according to your needs
  const debouncedSearchTerm = UseDebounce(searchTerm, 300); 

  useEffect(() => {
    // Here you can trigger your search logic, like an API call
    // For demonstration, let's just console log the debounced search term
    console.log("Search triggered with term:", debouncedSearchTerm);
  }, [debouncedSearchTerm]);

  const handleInputChange = (event) => {
    setSearchTerm(event.target.value);
  };

  return (
    <div>
      <input
        type="text"
        placeholder="Search..."
        value={searchTerm}
        onChange={handleInputChange}
      />
      <ul>
        {searchResults.map((result, index) => (
          <li key={index}>{result}</li>
        ))}
      </ul>
    </div>
  );
}    
export default SearchComponent;

Are there any limits on the width of elements in HTML?

I’m making a slider. The problem is that when there are more than 8 slides, the slider breaks (the forward button disappears, and the width of the slide increases). Perhaps the problem is that there is too much content in them? But how to solve this? Here’s my code:

body {
  font-family: Arial, sans-serif;
  margin: 0;
  padding: 0;
  background-color: #2a2a2a;
  color: white;
}

.slider-section {
  padding: 20px;
  background-color: #1e1e1e;
  border-radius: 10px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
  margin: 20px auto;
  max-width: 1200px;
  text-align: center;
}

.slider-container {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  position: relative;
  overflow: hidden;
}

.slider {
  display: flex;
  transition: transform 0.5s ease;
  width: calc(100% * 7);
}

.slide {
  min-width: 100%;
  flex: 0 0 100%;
  box-sizing: border-box;
  padding: 20px;
  text-align: center;
  overflow: hidden;
}

.slide-image img {
  width: 100%;
  height: auto;
  border-radius: 8px;
  margin-bottom: 15px;
}

.slide-title {
  font-size: 1.5rem;
  margin-bottom: 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.slide-description {
  font-size: 1rem;
  color: #ccc;
  line-height: 1.5;
  max-height: 6em;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}

.slider-arrow {
  flex: 0 0 10%;
  background: transparent;
  border: none;
  color: white;
  font-size: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.3s ease;
  outline: none;
  z-index: 100;
}

.slider-arrow:hover {
  background-color: rgba(0, 0, 0, 0.5);
  transform: scale(1.1);
}

@media (max-width: 768px) {
  .slider-arrow {
    display: none;
  }
}
<section class="slider-section">
<div class="slider-container">
  <button class="slider-arrow slider-arrow-left">
    <i class="fas fa-chevron-left"></i>
  </button>
  <div class="slider">
    <div class="slide">
      <div class="slide-image">
        <img src="placeholder.jpg">
      </div>
      <div class="slide-content">
        <h3 class="slide-title">Slide 1</h3>
        <p class="slide-description">Some desc</p>
      </div>
    </div>
    <div class="slide">
      <div class="slide-image">
        <img src="placeholder.jpg">
      </div>
      <div class="slide-content">
        <h3 class="slide-title">Slide 2</h3>
        <p class="slide-description">Some desc</p>
      </div>
    </div>
    <div class="slide">
      <div class="slide-image">
        <img src="placeholder.jpg">
      </div>
      <div class="slide-content">
        <h3 class="slide-title">Slide 3</h3>
        <p class="slide-description">Some desc</p>
      </div>
    </div>
    <div class="slide">
      <div class="slide-image">
        <img src="placeholder.jpg">
      </div>
      <div class="slide-content">
        <h3 class="slide-title">Slide 4</h3>
        <p class="slide-description">Some desc</p>
      </div>
    </div>
    <div class="slide">
      <div class="slide-image">
        <img src="placeholder.jpg">
      </div>
      <div class="slide-content">
        <h3 class="slide-title">Slide 5</h3>
        <p class="slide-description">Some desc</p>
      </div>
    </div>
    <div class="slide">
      <div class="slide-image">
        <img src="placeholder.jpg">
      </div>
      <div class="slide-content">
        <h3 class="slide-title">Slide 6</h3>
        <p class="slide-description">Some desc</p>
      </div>
    </div>
    <div class="slide">
      <div class="slide-image">
        <img src="placeholder.jpg">
      </div>
      <div class="slide-content">
        <h3 class="slide-title">Slide 7</h3>
        <p class="slide-description">Some desc</p>
      </div>
    </div>
    <div class="slide">
      <div class="slide-image">
        <img src="placeholder.jpg">
      </div>
      <div class="slide-content">
        <h3 class="slide-title">Slide 8</h3>
        <p class="slide-description">Some desc</p>
      </div>
    </div>
    <div class="slide">
      <div class="slide-image">
        <img src="placeholder.jpg">
      </div>
      <div class="slide-content">
        <h3 class="slide-title">Slide 9</h3>
        <p class="slide-description">Some desc</p>
      </div>
    </div>
  </div>

  <button class="slider-arrow slider-arrow-right">
    <i class="fas fa-chevron-right"></i>
  </button>
</div>
</section>
document.addEventListener("DOMContentLoaded", () => {
  const slider = document.querySelector(".slider");
  const slides = document.querySelectorAll(".slide");
  const arrowLeft = document.querySelector(".slider-arrow-left");
  const arrowRight = document.querySelector(".slider-arrow-right");

  let currentIndex = 0;

  function updateSlider() {
    slider.style.transform = `translateX(-${currentIndex * 100}%)`;
  }

  arrowRight.addEventListener("click", () => {
    if (currentIndex < slides.length - 1) {
      currentIndex++;
      updateSlider();
    } else {
      currentIndex = 0;
      updateSlider();
    }
  });

  arrowLeft.addEventListener("click", () => {
    if (currentIndex > 0) {
      currentIndex--;
      updateSlider();
    } else {
      currentIndex = slides.length - 1;
      updateSlider();
    }
  });

  let startX = 0;
  let isSwiping = false;

  slider.addEventListener("touchstart", (e) => {
    startX = e.touches[0].clientX;
    isSwiping = true;
  });

  slider.addEventListener("touchmove", (e) => {
    if (!isSwiping) return;
    const currentX = e.touches[0].clientX;
    const diff = startX - currentX;

    if (Math.abs(diff) > 50) {
      if (diff > 0 && currentIndex < slides.length - 1) {
        currentIndex++;
      } else if (diff < 0 && currentIndex > 0) {
        currentIndex--;
      }
      updateSlider();
      isSwiping = false;
    }
  });

  slider.addEventListener("touchend", () => {
    isSwiping = false;
  });
});

I already tried to change the script somehow (and even asked the AI), but this did not give any results

Stop “Attach Media” Popover Label from Appearing when using Hidden File Input in Chrome

I have a hidden file input with display: none in a form. Another button triggers a click event on the file input ref, which opens the browser’s file selection dialog. Then I have an onChange event that handles the file processing after the user clicks Open/Submit on the browser’s dialog.

The issue is that when the browser’s dialog closes, a label then pops up under the cursor that says “Attach Media”. I don’t know where this is coming from. I can click on my screen to stop the label appearing, but when I do this programmatically, it still appears and I don’t know why. I have tried dispatching click events to a few different areas of the page after a timeout. I have also tried blurring the input, disabling drag events on the input, and resetting the input’s file value, as well as a combination of all of these. I have also tried hiding the input in a few different ways, and assigning a new key to the input element after file selection.

The only way I can stop it appearing is with manual input but I don’t understand why. Here’s an example of code that I have tried. If I click anywhere on this element after the dialog closes, the label doesn’t appear, but this programmatic click event doesn’t work for some reason.

setTimeout(() => {
  const modalElement = document.getElementById('upload-modal')
  modalElement.dispatchEvent(new MouseEvent('click', { bubbles: true }))
}, 0)

How to disable unselecting previously selected options for a multiple select element?

I am working on the “tags selector” below in JavaScript, without using any plugin.

const tagsList = document.querySelector(".tags-list")
const tagActions = document.getElementById("tagActions")
const tagSelector = document.getElementById("tags")
const tagToggler = document.getElementById("tagSelectorToggler")
var selectedTags = new Set()

function filterTags(event) {
  var query = event.target.value
  var availableTags = Array.from(tagSelector.options)

  availableTags.forEach(function (option) {
    if (!option.text.toLowerCase().includes(query.toLowerCase())) {
      option.classList.add("d-none")
    } else {
      option.classList.remove("d-none")
    }
  })
}

function toggleTagSelector(event) {
  if (event.target.tagName !== "BUTTON" && event.target.tagName !== "SPAN") {
    tagActions.classList.toggle("d-none")
    tagToggler.classList.toggle("active")
  }
}

function renderTags() {
  tagsList.innerHTML =
    [...selectedTags]
      .sort()
      .map(
        (tag) =>
          `<li class="tag"
            ><span class="value">${tag}</span>
            <button>&times;</button>
         </li>`,
      )
      .join("") ||
    `<li class="text-muted">Click and select one or more tags from the list</li>`
  for (const option of tagSelector.options) {
    option.selected = selectedTags.has(option.textContent)
  }
}

tagsList.addEventListener("click", function (event) {
  if (event.target.tagName !== "BUTTON") return
  const span = event.target.closest("LI").children[0]
  selectedTags.delete(span.textContent)
  renderTags()
})

tagSelector.addEventListener("change", function () {
  selectedTags = new Set(
    Array.from(tagSelector.options)
      .filter((option) => option.selected)
      .map((option) => option.textContent),
  )
  renderTags()
})
.tags-list {
  min-height: 40px;
  list-style-type: none;
}
.tags-list .tag {
  line-height: 1;
  white-space: nowrap;
  background: #f2f2f2;
  border: 1px solid #e6e3e3;
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  font-size: 13px;
  padding: 3px 8px;
  margin-bottom: 2px;
}
.tags-list .tag button {
  background: #ff9292;
  color: #720000;
  border: none;
  width: 18px;
  height: 18px;
  font-size: 12px;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  margin-left: 6px;
  border-radius: 50%;
}
.form-control:focus, .form-select:focus {
  box-shadow: none;
}
/* Tags */
.toggler {
  position: absolute;
  right: 5px;
  margin-top: 8px;
  color: #777;
  cursor: pointer;
}
.toggler.active {
  transform: rotate(180deg);
}
.tag-select option {
  padding: 3px 8px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>

<div class="container my-2">
  <div class="form-group position-reletive">
    <label for="tags" class="text-muted fw-bold pb-1">Tags</label>
    <div class="position-relative">
      <span
        id="tagSelectorToggler"
        class="toggler"
        onclick="toggleTagSelector(event)"
      >
        <i class="fas fa-chevron-down"></i>
      </span>
      <ul
        class="form-control tags-list mb-1"
        onclick="toggleTagSelector(event)"
      >
        <li class="text-muted">
          Click and select one or more tags from the list
        </li>
      </ul>
    </div>

    <div id="tagActions" class="d-none">
      <input
        oninput="filterTags(event)"
        type="search"
        class="form-control mb-1"
        placeholder="Filter available tags"
      />

      <select id="tags" name="tags" class="form-select tag-select" multiple>
        <option value="Apple">Apple</option>
        <option value="Banana">Banana</option>
        <option value="Blackberry">Blackberry</option>
        <option value="Blueberry">Blueberry</option>
        <option value="Cherry">Cherry</option>
        <option value="Cranberry">Cranberry</option>
        <option value="Grapes">Grapes</option>
        <option value="Kiwi">Kiwi</option>
        <option value="Mango">Mango</option>
        <option value="Orange">Orange</option>
        <option value="Peach">Peach</option>
        <option value="Pear">Pear</option>
        <option value="Pineapple">Pineapple</option>
        <option value="Raspberry">Raspberry</option>
        <option value="Strawberry">Strawberry</option>
        <option value="Watermelon">Watermelon</option>
      </select>
    </div>
  </div>
</div>

I have developed a way to search (filter) through the list of available tags, wich is the <select multiple> element.

The problem I am faced with is that, when I search for a certain item and click it, the previously selected items are deselected.

What is the easiest and most reliable way to prevent this behavior?

Changing Const Item from text characters to image url

I have this bit of js that basically creates a slot machine effect. It rotates between 1-12 and stops on one of them randomly. Works perfectly fine. but I would PREFER to change these to images but I’ve struggled to figure that out. Any help?

I did try simply inserting html in the place and it just displays the text. I’m not at all good at writing/editing jscript.

(function () {
  const items = [
    '1',
    '2',
    '3',    
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
    '10',
    '11',
    '12',
  ];
  const doors = document.querySelectorAll('.door');
  
  document.querySelector('#spinner').addEventListener('click', spin);
  document.querySelector('#reseter').addEventListener('click', init);

  function init(firstInit = true, groups = 1, duration = 1) {
    for (const door of doors) {
      if (firstInit) {
        door.dataset.spinned = '0';
      } else if (door.dataset.spinned === '1') {
        return;
      }

      const boxes = door.querySelector('.boxes');
      const boxesClone = boxes.cloneNode(false);
      const pool = ['❓'];

      if (!firstInit) {
        const arr = [];
        for (let n = 0; n < (groups > 0 ? groups : 1); n++) {
          arr.push(...items);
        }
        pool.push(...shuffle(arr));

        boxesClone.addEventListener(
          'transitionstart',
          function () {
            door.dataset.spinned = '1';
            this.querySelectorAll('.box').forEach((box) => {
              box.style.filter = 'blur(1px)';
            });
          },
          { once: true }
        );

        boxesClone.addEventListener(
          'transitionend',
          function () {
            this.querySelectorAll('.box').forEach((box, index) => {
              box.style.filter = 'blur(0)';
              if (index > 0) this.removeChild(box);
            });
          },
          { once: true }
        );
      }

      for (let i = pool.length - 1; i >= 0; i--) {
        const box = document.createElement('div');
        box.classList.add('box');
        box.style.width = door.clientWidth + 'px';
        box.style.height = door.clientHeight + 'px';
        box.textContent = pool[i];
        boxesClone.appendChild(box);
      }
      boxesClone.style.transitionDuration = `${duration > 0 ? duration : 1}s`;
      boxesClone.style.transform = `translateY(-${door.clientHeight * (pool.length - 1)}px)`;
      door.replaceChild(boxesClone, boxes);
    }
  }

  async function spin() {
    init(false, 1, 2);
    
    for (const door of doors) {
      const boxes = door.querySelector('.boxes');
      const duration = parseInt(boxes.style.transitionDuration);
      boxes.style.transform = 'translateY(0)';
      await new Promise((resolve) => setTimeout(resolve, duration * 100));
    }
  }

  function shuffle([...arr]) {
    let m = arr.length;
    while (m) {
      const i = Math.floor(Math.random() * m--);
      [arr[m], arr[i]] = [arr[i], arr[m]];
    }
    return arr;
  }

  init();
})();

How to highlight selected text in a rich text editor when the selection spans multiple HTML tags?

I’m implementing text highlighting functionality in a custom text editor using vanilla javascript, similar to how MS Word highlights text. The issue I’m encountering is that when a user selects text that spans multiple HTML tags, the selection is not accessible in a way that allows me to highlight it properly.

Here’s an example of how the text is structured in my editor:

<p>I never [mouse down] found out who sent me the flowers.</p>
<p>It was my first flight. I was <b>nervous</b> as the plane took off.
  <span class='highlight'>I tried many times to[mouse up] contact her. In the end I gave up.</span>
</p>

In this case, the user would select the text starting from “I never” (indicated by [mouse down]) to “contact her” (indicated by [mouse up]), and I want to apply a highlight to the selected portion of text.

What I need help with: How can I implement a solution that allows me to highlight text that is selected across multiple tags?

I can’t find out the solution for this problem.

javascript mathematical constants do not work in equation demo [closed]

How can mathematical constants be expressed in Dynagraph?

π (pi): The ratio of a circle’s circumference to its diameter.
e (Euler’s number): The base of the natural logarithm.
φ (golden ratio): A special number found in nature and art, approximately 1.618.
√2 (square root of 2): The number that when multiplied by itself equals 2.

I tried the google returns for javascript mathematical constants and got E (Euler) and PI (3.14159…), neither of which worked in the equations plotter demo

Difference between form data and x www form urlencoded

So I’m new to programming and recently started learning Backend. Okay so recently I came across a problem with postman while making POST request. So when I wrote a controller for registering a user I used postman for testing and make a simple POST request with form-data which consist of fields like username, email, fullName, avatar, coverImage, password. And it worked perfectly fine and user got registered in the Database.

But when i did the same thing with my login controller like make a POST request with form-data which consist of fields username, password. It started throwing error like cannot read the properties of undefined. After some debugging I found out that the body in the request has an empty object and that’s why I’m getting this error. I tried sending Raw data from postman but that didn’t worked either, but finally when I tried with x-www-form-urlencoded it worked.

So my question is why does it worked with x-www-form-urlencoded and not with form-data and Raw? and also why was I getting an empty object while i was sending form-data and Raw data.

Here’s my registerUser controller –

const registerUser = asyncHandler( async (req, res) => {

    const {fullName, email, username, password} = req.body

    if ([fullName, email, username, password].some(field => field?.trim() === "")) { // we're using optional chaining to avoid running trim() on null or undefined field
        throw new ApiError(400, "All fields are required!") // Checking if all the fields are non-empty
    } else if (!email?.includes("@") || !email?.includes(".")) { // Checking if email is vaild or not
        throw new ApiError(400, "Please enter a vaild email") // Its not a hard check for email
    }

    const existedUsername = await User.findOne({username})
    const existedEmail = await User.findOne({username})

    if (existedUsername) {
        throw new ApiError(409, "Username already exist")
    } else if (existedEmail) {
        throw new ApiError(409, "Email is already linked to a different account")
    }

    let avatarLocalPath;
    if (req.files && Array.isArray(req.files.avatar) && req.files.avatar.length > 0) {
        avatarLocalPath = req.files?.avatar[0]?.path; // multer gives us the access of .files field in the request
    }
    
    let coverImageLocalPath; // manually checking if coverImage is provided or not before chaining
    if (req.files && Array.isArray(req.files.coverImage) && req.files.coverImage.length > 0) {
        coverImageLocalPath = req.files.coverImage[0].path; 
    }
    
    if (!avatarLocalPath) {
        throw new ApiError(400, "Avatar Local path is required!")
    }

    const avatar = await uploadOnCloudinary(avatarLocalPath);
    // console.log(avatar)
    const coverImage = await uploadOnCloudinary(coverImageLocalPath);
    
    if (!avatar) {
        throw new ApiError(400, "Avatar file is required")
    }

    const user = await User.create({
        fullName,
        avatar: avatar.url,
        coverImage: coverImage?.url || "",
        username: username.toLowerCase(),
        email,
        password,
    })

    const createdUser = await User.findById(user._id).select("-password -refreshToken"); 

    if (!createdUser) {
        throw new ApiError(500, "Something went wrong while registering the user")
    }

    return res.status(201).json(
        new ApiResponse(200, createdUser, "User registered Successfully")
    )
})

Here’s loginUser controller –

const loginUser = asyncHandler( async (req, res) => {

    const {email, username, password} = req.body

    if (!(username || email)) {
        throw new ApiError(400, "Username or Email is required to Login")
    }

    const user = await User.findOne({
        $or: [{username}, {email}]
    })

    if (!user) {
        throw new ApiError(404, "User does not exist");
    }

    const isPasswordValid = await user.isPasswordCorrect(password);

    if (!isPasswordValid) {
        throw new ApiError(401, "Invaild user password");
    }

    const {accessToken, refreshToken} = await generateAccessAndRefreshTokens(user._id);

    const loggedInUser = await User.findById(user._id).select("-password -refreshToken");

    const options = {
        httpOnly: true,
        secure: true
    }

    return res
    .status(200)
    .cookie("accessToken", accessToken, options)
    .cookie("refreshToken", refreshToken, options)
    .json(new ApiResponse(
            200,
            {
                user: loggedInUser,
                accessToken,
                refreshToken
            },
            "User logged In Successfully")
    )
})