observablehq / feedback

Customer submitted bugs and feature requests

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Button input stops responding in certain conditions on observable platform.

CarlosLagarto opened this issue · comments

The button input stops responding with certain conditions, as the minimal example bellow.

To Reproduce

  1. make a test page in the observable platform dev environment (code bellow).
  2. run the page
  3. without the browser debugger the test page reacts ok
  4. activate the browser debugger (browser elipse->more tools->developer tools)
  5. now the buttons shouldn't react

Expected behavior
The buttons were supposed to react in debugger mode

Desktop (please complete the following information):

  • OS: Ubuntu Linux desktop (Ubuntu 22.04.4 LTS)
  • Browser chrome Version 122.0.6261.128 (Official Build) (64-bit)

Additional context
Minimal example to reproduce...at least on my configuration :-)

---
title: test Example
# toc: false
# pager: false
# footer: false
# theme: "dashboard"
---
Test
const defaultInput = v => html.fragment`<input style="width: 100%;" type="text" value="${v}" />`;
const datetimeInput = v => html.fragment`<input style="width: 100%;" type="datetime-local" value="${v}" />`;
const selectInput = v => html.fragment`<select>
            ${html.fragment`<option value="Option1" selected=${v==="Option1"}>Option1</option>`}
            ${html.fragment`<option value="Option2" selected=${v==="Option2"}>Option2</option></select>`}`;

const row_values = [];
const mut_values= Mutable(row_values);

function listInput (
  { 
    columns = [
        { 
          name : "Col1",
          input : defaultInput,   
          value : null, 
          min_width: "80px",
          defaultValue : 'value1'
        },
        { 
          name : "Col2",
          input : defaultInput,   
          value : null, 
          min_width: "200px",
          defaultValue : 'value2'
        },
        { 
          name : "Col3",
          input : defaultInput,   
          value : null, 
          min_width: "50px",
          defaultValue : '1.0'
        },
        { 
          name : "Col4",
          input : selectInput,   
          value : null, 
          min_width: "50px",
          defaultValue : 'Buy'
        },
        { 
          name : "Date",
          input : datetimeInput,   
          value : null, 
          min_width: "200px",
          defaultValue : '2023-01-02T01:00:00'
        }
      ],
    cfg = {
      min : 0,
      max : 0,  
    }
  } = {}) {
   
  // This is a state variable that we will change as events occur on the input
  // let row_values = [];
  mut_values.value.push(columns.map((row) => { return { 
      value: row.value !== null ? row.value : row.defaultValue, 
      name: row.name
  }}));
  
  // Templates
  const inputRow = (row, i) => html.fragment`
    <tr>
      ${row.map( (col, j) => html.fragment`<td onchange=${e => changeValueAt(i, j, e.target.value)}>${columns[j].input(col.value)}</td>`)}
      <td>
        <button onclick=${e => removeRow(i)}>&times;</button>
      </td>
    </tr>`

  const headerRow = () => html.fragment`<tr>
    ${columns.map((col) => html.fragment`<th style="width:${col.min_width};">${col.name}</th>`)}
    <td>
      <button onclick=${addRow}>+</button>
    </td>
  </tr>`
   
  // Rerender Helpers
  const rerenderTbody = () => {
    const tbody = output.querySelector('tbody')
    tbody.innerHTML = ''
    tbody.appendChild(html.fragment`${mut_values.value.map(inputRow)}`)
  }
  
  const rerenderTheader = () => {
    const theader = output.querySelector('thead')
    theader.innerHTML = ''
    theader.appendChild(headerRow())    
  }

  const rerender = () => {
    rerenderTheader()
    rerenderTbody()
  }

  // Event Dispatcher
  const dispatchInputEvent = () => {
    output.value = mut_values
    output.dispatchEvent(new CustomEvent('input'))
  }
  
  // Event Handlers
  const addRow = () => {
    mut_values.value.push(columns.map((row) => { return { 
      value: row.value !== null ? row.value : row.defaultValue,
      name: row.name,
    }}));
    rerender()
    dispatchInputEvent()
  }
  
  const removeRow = removeIdx => {
    mut_values.value = mut_values.value.filter((_, i) => i !== removeIdx)
    rerender()
    dispatchInputEvent()
  }
  
  const changeValueAt = (i, j, value) => {
    mut_values.value[i][j].value = value
    rerender()
    dispatchInputEvent()
  }
  
  const output = html`<table style="width: 100%;table-layout: fixed;"}>
    <thead>
      ${headerRow()}
    </thead>
    <tbody>
      ${mut_values.value.map(inputRow)}
    </tbody>
  </table>`
  
  output.value = mut_values
  return output
}

  const table_input = listInput();
<div class="card" style="">
    <!-- if we add a display: inline-flex to the div the buttons stops responding -->
    <div class="card" style="margin: 0;display: inline-flex;">
    <!-- the next div should be uncommented and comment the div above to see the behaviour-->
    <!-- <div class="card" style="margin:0;">  -->
        <!-- but only happens it the div have another div card inside, as the next one-->
        <div class="card" style="width:400px">Select elements</div>    
        <div class="card">${table_input}</div>  
    </div>
</div>

The button stops responding because enabling the debugger pauses script execution. If you still believe this to be a bug, please provide a minimal example and the exact steps to reproduce.

I think something happened in the communication.

I just open the developer tools as I said in the steps to reproduce. You don't need to pause the debugger (that off course would stop script execution).
If you copy the code I sent (minimal steps to reproduce) to a md file for the observable platform will see this behavior.

"Minimal example" means reducing your code to the bare minimum that is required to demonstrate the problem, by removing anything that does not contribute to it. I would expect a minimal example to only have a one button element and to not contain any code related to templating.

Neither "now the buttons shouldn't react" nor "The buttons were supposed to react in debugger mode" describes what exactly you expect to happen when clicking the button.

I suggest that we continue this conversation in the forum thread that you had created before. If that happens to surface a bug I'm happy to reopen this issue.