Skip to content

Custom formatter or editor per column #178

Open

Description

@taschini

Hi there,

I was wondering, what is the best way to specify a custom formatter or editor per column?

For instance, formatting floats using thousands separators ("1,234.56").

Activity

  1. taschini commented on Mar 7, 2018

    @taschini
    Author

    My current solution is to set the formatter in Javascript after the QgridWidget has been displayed:

    Take for instance the dataframe

    import pandas as pd
    from numpy.random import randn
    df = pd.DataFrame({
        'B' : pd.Series(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
                   '2013-01-05', '2013-01-06', '2013-01-07', '2013-01-08', '2013-01-09'],index=list(range(9)),dtype='datetime64[ns]'),
        'C' : pd.Series(randn(9)*10**5,index=list(range(9)),dtype='float64'),
        'E' : pd.Categorical(["washington", "adams", "washington", "madison", "lincoln","jefferson", "hamilton", "roosevelt", "kennedy"]),
        'F' : ["foo", "bar", "buzz", "bippity","boppity", "foo", "foo", "bar", "zoo"] })

    which can be rendered as

    import qgrid
    qgrid.show_grid(df)

    The custom formatter for column "C" can be specified by

    from IPython.display import Javascript, HTML
    display(HTML('<style>.slick-cell.number {text-align: right}</style>'))
    display(Javascript("""\
    window.slick_grid.setColumns(window.slick_grid.getColumns().map(x => {
        if (x.id === 'C') {
            x.formatter = (r, c, v, cd, dc) =>
            (v === null ? '' : v.toLocaleString(
                'en', {'minimumFractionDigits': 2, 'maximumFractionDigits': 2}));
        }
        return x
    }));
    """))

    This solution is clearly sub-optimal since it uses a global variable (window.slick_grid) that I believe you introduced only for trouble-shooting.

    Do you have any idea on how to achieve the same result in a proper way?

  2. TimShawver commented on Mar 7, 2018

    @TimShawver
    Contributor

    Cool! I'm afraid I have not worked out a proper way to do this yet...it's one of the most requested features though so I'm hoping I can find some time to work on it soon. Maybe what I should do is let people pass in a javascript function for formatting the column as you're doing here, but let them do it at the time with qgrid is constructed....

    I've also had requests for conditionally rendering ipywidget controls within cells (like buttons, etc), which I think would be really cool but likely more complex to implement, so maybe starting with a js-based solution like you have here would be a good start.

    Anyways, sorry I don't have a better answer yet, and thanks for the feedback...it's really helpful to see a concrete example of the types of things people want to be able to do.

  3. taschini commented on Mar 8, 2018

    @taschini
    Author

    I have two separate suggestions:

    1. Keep a reference to the Slick.Grid object within the DOM element: something like

      this.$el.data('slickgrid', this.slick_grid)
      

      instead of, or perhaps together with,

      window.slick_grid = this.slick_grid
      

      In this way, you have are still able to retrieve the grid object from the console via DOM for troubleshooting, but you would also make it easier for people to integrate qgrid with other Javascript code, especially in the case of multiple grid objects per notebook.

    2. Like you said, add the possibility, somewhere like here, to post-process the column specifications: something like

      this.columns = eval(this.model.get('postprocess_columns'))(this.columns);

      or, perhaps, due to the subtelties of eval,

      this.columns = Function('columns', this.model.get('postprocess_columns'))(this.columns);
  4. TimShawver commented on Mar 8, 2018

    @TimShawver
    Contributor

    Great suggestions, thanks. I will give those a shot and hopefully include them in an upcoming release. Also if you have time to implement/test them out yourself and open a PR, that might accelerate the process a bit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions