2

I have an issue with the following js. It sounds very silly but the following js keeps unchecking the 2 first checkbox (in <div id="shortcut1"></div> and <div id="shortcut2"></div>). I tested the script with different option, changing the params in cmdInfo. My conclusion is that no matter what the script will never check the 2 first checkbox at the end.

Do you have any idea regarding the issue. I spend hours on this but I can't figure out. Thanks a lot for your help !

https://jsfiddle.net/bqaude3h/2/

const URL_PLACEHOLDER = 'your url'

let commands = [
    { name: "shortcut1", description: null, shortcut: "Alt+W" },
    { name: "shortcut2", description: null, shortcut: "Alt+Q" },
    { name: "shortcut3", description: null, shortcut: "Alt+S" }
]
let cmdInfo = {
    "shortcut1": {
        "storeSearchHistory": true,
        "url": "https://test.com",
        "history": ['test']
    },
    "shortcut2": {
        "storeSearchHistory": false,
        "url": ""
    },
    "shortcut3": {
        "storeSearchHistory": true,
        "url": ""
    }
}

let html, div, existingHistory;
commands.forEach(cmd => {

    html = `
    <div id="${cmd.name}" class="sc-div">
        <div class="flex-container">
            <input type="text" class="shortcut" value="${cmd.shortcut}" />
            <input type="url" class="url" placeholder="${URL_PLACEHOLDER}"
                    value="${cmdInfo[cmd.name].url}" />
        </div>
        <div class="history-div">
            <button>View search history</button>
            <input type="checkbox" class="store-search-history" />
            <label><small>Save search history</small></label>
        </div>
    </div>
    `
    document.querySelector('#shortcuts').innerHTML += html;

    try {
        existingHistory = Boolean(cmdInfo[cmd.name].history.length)
    } catch {
        existingHistory = false;
    }

    div = document.getElementById(cmd.name);
    div.querySelector('button').disabled = !existingHistory;

    div.querySelector('.store-search-history').checked = cmdInfo[cmd.name].storeSearchHistory;
});
halden
  • 23
  • 4

2 Answers2

2

The issue is with this line: document.querySelector('#shortcuts').innerHTML += html;

You can read about Why is “element.innerHTML+=” bad code?. Basically, the browser will re-parse the constructed DOM multiple times which might cause to break reference.

This is a working example:

let commands = [{
    name: "shortcut1",
    description: null,
    shortcut: "Alt+W"
  },
  {
    name: "shortcut2",
    description: null,
    shortcut: "Alt+Q"
  },
  {
    name: "shortcut3",
    description: null,
    shortcut: "Alt+S"
  }
]
let cmdInfo = {
  "shortcut1": {
    "storeSearchHistory": true,
    "url": "https://some_url.com"
  },
  "shortcut2": {
    "storeSearchHistory": false,
    "url": ""
  },
  "shortcut3": {
    "storeSearchHistory": true,
    "url": ""
  }
}

let html, div, existingHistory, URL_PLACEHOLDER;
commands.forEach(cmd => {

  html = `
    <div id="${cmd.name}" class="sc-div">
        <div class="flex-container">
            <input type="text" class="shortcut" value="${cmd.shortcut}" />
            <input type="url" class="url" placeholder="${URL_PLACEHOLDER}"
                    value="${cmdInfo[cmd.name].url}" />
        </div>
        <div class="history-div">
            <button>
                <img src="icons/box-open-solid.svg"> View search history
            </button>
            <input type="checkbox" class="store-search-history" />
            <label><small>Save search history</small></label>
        </div>
    </div>
    `
  //document.querySelector('#shortcuts').innerHTML += html;
  document.querySelector('#shortcuts').insertAdjacentHTML('beforeend', html);

  try {
    existingHistory = Boolean(cmdInfo[cmd.name].history.length)
  } catch (e) {
    existingHistory = false;
  }

  div = document.getElementById(cmd.name);
  div.querySelector('button').disabled = !existingHistory;
  div.querySelector('.store-search-history').checked = cmdInfo[cmd.name].storeSearchHistory;
});
<div id='shortcuts'>

</div>
Kalimah
  • 11,217
  • 11
  • 43
  • 80
1

You may use the conditional rendering for the input tag.


let commands = [
    { name: "shortcut1", description: null, shortcut: "Alt+W" },
    { name: "shortcut2", description: null, shortcut: "Alt+Q" },
    { name: "shortcut3", description: null, shortcut: "Alt+S" }
]
let cmdInfo = {
    "shortcut1": {
        "storeSearchHistory": true,
        "url": "https://some_url.com"
    },
    "shortcut2": {
        "storeSearchHistory": false,
        "url": ""
    },
    "shortcut3": {
        "storeSearchHistory": true,
        "url": ""
    }
    }

let html, div, existingHistory;
let URL_PLACEHOLDER="your placeholder"
commands.forEach(cmd => {

    html = `
    <div id="${cmd.name}" class="sc-div">
        <div class="flex-container">
            <input type="text" class="shortcut" value="${cmd.shortcut}" />
            <input type="url" class="url" placeholder="${URL_PLACEHOLDER}"
                    value="${cmdInfo[cmd.name].url}" />
        </div>
        <div class="history-div">
            <button>
                <img src="icons/box-open-solid.svg"> View search history
            </button>
            ${
                cmdInfo[cmd.name].storeSearchHistory?
                '<input type="checkbox" checked >'
                :'<input type="checkbox"  >'
            }
            <label><small>Save search history</small></label>
        </div>
    </div>
    `
    document.querySelector('#shortcuts').innerHTML += html;

    try {
        existingHistory = Boolean(cmdInfo[cmd.name].history.length)
    } catch {
        existingHistory = false;
    }

    div = document.getElementById(cmd.name);
    div.querySelector('button').disabled = existingHistory;
    // div.querySelector('.store-search-history').checked = cmdInfo[cmd.name].storeSearchHistory;
});


SUDHIR KUMAR
  • 381
  • 4
  • 10