Dynamic visibility of complex substructures

Hey everyone,

the app I’m building contains eight instances of complex substructures, which themselves contain input elements and rely on callbacks working. However, to keep the app is uncluttered as possible, I’d like to show only the active ones.

For this purpose, I am currently using a Checklist and am trying to create multiple callbacks in a concise manner. I draw my inspiration from this thread:

Now, my problem is: Dash presents me with two possibilities: returning child-elements to change the layout dynamically (which is problematic because I can’t creat callbacks at the same time, or to hide elements using Display: none.

My code looks like this

output_elements = ['servo_{}'.format(i) for i in range(1,9)]
print(output_elements)

def create_callback(output):
	def callback(input_value):
		print(input_value)
		if output_element[len(output_element)-1:] in input_value:
			return {'display': 'block'}
		return {'display': 'none'}
	return callback

for output_element in output_elements:
	print(output_element)
	dynamically_generated_function = create_callback(output_element)
	print(dynamicallyGeneratedFunction)
	app.callback(Output(output_element, 'style'), [Input('servo_check', 'values')])(dynamically_generated_function)

Now, what happens, is that nothing works, except when I check ‘8’, which reveals or hides all eight sub-units. I’m guessing this has to do with the way I define the callback function, which is probably being overwritten 7 times until only the last one remains active. What I do not understand, is why it hides/shows everything. This might also have to do with the way I create the elements, which is basically done like this:

html.Div(
			children=[
				html.Div([..................
...............................], className='controller_container twelve columns', id='servo_{}'.format(i)) for i in range(1,9)
			],
			id='servo_control',
			style={},
			className='row'
		)

Nevermind, I found the mistake… goddammit. For all those intrested:

Apart from the fact, that

print(dynamicallyGeneratedFunction)

gives a syntax error, I forgot about the scope entirely and falsely referred to output_element in the callback function, it should, of course, be:

output_elements = ['servo_{}'.format(i) for i in range(1,9)]

def create_callback(output):
	def callback(input_value):
		if output[len(output)-1:] in input_value:
			return {'display': 'block'}
		return {'display': 'none'}
	return callback

for output_element in output_elements:
	dynamically_generated_function = create_callback(output_element)
	app.callback(Output(output_element, 'style'), [Input('servo_check', 'values')])(dynamically_generated_function)

Thanks for posing your mistake klnrdknt. Solving a similar problem was made much easier with your code.

1 Like