Setting cell attributes

Tags: #<Tag:0x00007fd2c205dd08>

We’re looking to set TD cell attributes so we can hook into Tippy JS to show error tooltips using values from afterValidate().

We’re also using multiple cell renders.

So my question is, how do we set a data-* attribute on cells?

I didn’t get any luck with cells() so I’m next looking at afterRenderer().

OK, so getting somewhere with this.

The problem I have now is that out validation is asynchronous, so afterRender() and access to td and valid is called before out validation is finished.

Can we trigger it again when our validation digest has finished?

Hey Dave,

That’s a cool lib. Can you share your latest progress. Do you pack it into renderer https://jsfiddle.net/of8g0beq/?

Can we trigger it again when our validation digest has finished?

you can can render() to rerender the table and validateCells() to revalidate.

Actually it’s a bit of a pain to work with! Not sure if it’s trying to do too much, or just a poor API / docs.

There are 3 OS packages working together: Handsontabe, Vee Validate and now Tippy. Here’s how it’s looking:

Have lots to do today but will see if I can build you something simpler!

Also

  • won’t a re-render destroy anything we have done in afterRenderer() ?
  • doesn’t validateCells() validates the entire dataset? This could be expensive.

This definitely looks better than our comments and should provide more privileges.

won’t a re-render destroy anything we have done in afterRenderer() ?

  • hard to tell. I’d need to see the code.

doesn’t validateCells() validates the entire dataset? This could be expensive.

  • yes, it will. We’re halfway to introduce eco-renderers. It takes a lot of side-fixes and refactoring.

OK, so thinking creatively around this one now…

Solution 1

The author of VeeValidate and I are going to patch the lib to enable sync validations

However this would still need us to RE-validate in the afterValidate hook.

The trick is clearly to use any error generated in the validate function, so…

Solution 2

Save validation results in our table wrapper, and use them in the hook:

      initValidator () {
        // update validator
        this.validator = this.settings.validator
        this.validator.setOptions(this.action, this.response, this.role)

        // add column validators
        this.settings.columns.forEach(column => {
          if (column.validator || column.editor || !column.readOnly) {
            column.validator = (value, process) => {
              this.validator.validateField(value, column.data).then(error => {
                this.current.error = error
                process(!error)
              })
            }
          }
        })
      },

This is used in a fairly straightforward but laborious series of callbacks and checks, which set table cell attributes:

  • beforeValidate() - store the row and column
  • afterValidate() - grab current.error setting and set it on another object (that stores sparse row and cell values) using the stored row and column data
  • afterRenderer() - if cell is not valid, write the row and cell it to the cell attributes (we would use afterOnCellMouseOver but it only supplies indices not prop names)

Using the tooltip lib, we then grab the row and prop from each cell as it is hovered, and check to see if there are any errors. If there are, we show the tooltip!

cell-validation

It’s rather involved, but seems to be working so far, and is the least hacky code we can write given the constraints so far.

One other thing…

We have cross-field validation constraints on our models, for example: “Term End Date cannot be before Settlement Date”.

This means that if we edit Settlement Date, we need Term End Date to validate itself.

Is there any way we can validate a row (externally) then use something like setCellMeta() to tell a cell to be invalid?

Otherwise, we will have to grab the row data in our validation closure, but it’s going to be expensive for initial table load (unless we flag it), and we won’t be able to set other cells as invalid if a change invalidates it (like the date example above).

I also posted a proposal on GitHub to pass any generated errors through to the validation callbacks:

1 Like

I do not see this working with the htInvalid (default class). It looks like when we attach the class externally (via setCellMeta) is it validated once again and the class is erased.
If your values are truly invalid (attach validator would mark them invalid), after calling validateRows you’ll get the same result as attaching a class and repainting the table.

Hmmm… did I know about validateRows() !?

I do a lot of coding in the console, so surely I would have seen?

I’ll investigate :smiley:

Also, the comment from @wojciech.czerniak on the GitHub issue regarding using cell meta to store errors sounds great.

I’m just looking at the checkbox renderer stuff from all those months ago, then will look at this again!

Yea, that was a good catch with the cell meta.