holoviz / panel

Panel: The powerful data exploration & web app framework for Python
https://panel.holoviz.org
BSD 3-Clause "New" or "Revised" License
4.73k stars 516 forks source link

Add Dict Widget #2700

Open sdc50 opened 3 years ago

sdc50 commented 3 years ago

It would be great to have a mapping widget that would allow you to edit key-value pairs that are stored in a dict object.

I have manually created an interface that does this, but it requires a lot of code and it's a little clunky.

image

```python def update_environ(self, event): _, is_key, i = event.obj.css_classes[0].split('_') is_key = is_key == 'key' i = int(i) if is_key: if i > -1: self.environment_variables[event.new] = self.environment_variables[event.old] del self.environment_variables[event.old] else: self.environment_variables[event.new] = None else: key = self.env_names[i].value self.environment_variables[key] = event.new self.param.trigger('environment_variables') def env_var_widget(self, val, tag, **kwargs): widget = pn.widgets.TextInput(value=val, css_classes=[tag], **kwargs) widget.param.watch(self.update_environ, ['value'], onlychanged=True) return widget @param.depends('environment_variables') def environment_variables_view(self): self.environment_variables.pop('', None) # Clear blank key if there is one self.env_names = list() self.env_values = list() self.env_browsers = list() for i, (k, v) in enumerate(self.environment_variables.items()): name_widget = self.env_var_widget(val=k, tag=f'env_key_{i}') val_widget = self.env_var_widget(val=str(v), tag=f'env_val_{i}') browser_widget = self.env_file_browser_widget(tag=f'env_browser_{i}') self.env_names.append(name_widget) self.env_values.append(val_widget) self.env_browsers.append(browser_widget) self.env_names.append(self.env_var_widget(val=None, tag='env_key_-1', placeholder='NEW_ENV_VAR')) self.env_values.append(self.env_var_widget(val=None, tag='env_val_-1', disabled=True)) self.env_browsers.append(self.env_file_browser_widget(tag='env_browser_-1', disabled=True)) self.env_names[0].name = 'Name' self.env_values[0].name = 'Value' return pn.Card( *[pn.Row(k, v, b, sizing_mode='stretch_width') for k, v, b in zip(self.env_names, self.env_values, self.env_browsers)], self.file_browser_col, title='Environment Variables', sizing_mode='stretch_width', ) ```

I think a native key-value widget would make this a lot easier to do and work much better.

Stubatiger commented 3 years ago

This would be specifically for string -> string mapping right?

Or how would that look like for nested keys/values?

MarcSkovMadsen commented 3 years ago

Maybe there would be some kind of dict/ json editor out there that could be easily wrapped using ReactiveHTML. For example

Or maybe ReactiveHTML could be a solution on its own.

sdc50 commented 3 years ago

This would be specifically for string -> string mapping right?

That was my thought, at least initially to provide a widget for string -> string. Perhaps as @MarcSkovMadsen suggested there could also be ways of supporting more complex mappings.