How to make a numeric input not editable?

I'm trying to write a code where the numeric input is uneditable on the web app for the user and already has a number in it (i.e. it's grayed out and users can't click it or type in it), but I can't find any resources that could help me. Is there a way to do that on Python Shiny?

Hi @mcnuggetx

if you look at reactive value example the inputs for increasing or decreasing the counter are just action buttons which are set and you can't change them. Could that solve your issue - instead of a numeric input make a button with the value you want and simply read out the value when you need it.

To make an input non-editable by the user, you want to include the disabled attribute to the HTML <input> tag. Unfortunately in both R and Python flavours of Shiny, you can't simply add a disabled attribute to the standard input methods, so we have to add this the long way.

In Python, we can see what HTML is produced when making a numeric input:

ui.input_numeric("obs", "Observations:", 10, min=1, max=100)
<div class="form-group shiny-input-container">
    <label class="control-label" id="obs-label" for="obs">Observations:</label>
    <input id="obs" type="number" class="shiny-input-number form-control" value="10" min="1" max="100"/>
</div>

We want to get a disabled attribute into the <input> so we are targetting the second child element of the outer <div> object. Modifying the example from the numeric input page, we can store the input separately and then modify the relevant attribute before using it in the UI:

from shiny import App, Inputs, Outputs, Session, render, ui

# Make a standard numeric input
obs_input = ui.input_numeric("obs", "Observations:", 10, min=1, max=100)
# Add the disabled tag to the second-child of the outer <div> object.
obs_input.children[1].attrs.update({'disabled': 'disabled'})

app_ui = ui.page_fluid(
    obs_input,
    ui.output_text_verbatim("value"),
)

def server(input: Inputs, output: Outputs, session: Session):
    @render.text
    def value():
        return input.obs()

app = App(app_ui, server)

This should create a disabled numeric input. You could apply the same method to other input types.

But be warned, this would be a client-side restriction and the user could re-enable the field from their side. You, as the developer, are responsible for doing a server-side sanity check that the user has not modified this value if it is later used for further calculations on the server.