简体   繁体   中英

How to prevent closing of cell edit mode on validation errors with custom vue components in ag-grid

I have succesfully rendered my own component as the cellEditor and would like and on-leave I would like it to try to validate the value and prevent the closing if it fails.

If I look at this then https://www.ag-grid.com/javascript-grid-cell-editing/#editing-api there's cancelable callback functions for editing. But in this callback function is there a way to access the current instantiated component? I would think that would be the easiest way to handle this.

I'm using vee-validate so the validation function is async, just to keep in mind.

I had a similar issue - albeit in AngularJS and the non-Angular mode for ag-grid - I needed to prevent the navigation when the cell editor didn't pass validation.

The documentation is not very detailed, so in the end I added a custom cell editor with a form wrapped around the input field (to handle the niceties such as red highlighting etc), and then used Angular JS validation. That got me so far, but the crucial part was trying to prevent the user tabbing out or away when the value was invalid so the user could at least fix the issue.

I did this by adding a value parser when adding the cell, and then within that if the value was invalid according to various rules, throw an exception. Not ideal, I know - but it does prevent ag-grid from trying to move away from the cell.

I tried loads of approaches to solving this - using the tabToNextCell events, suppressKeyboardEvent , navigateToNextCell , onCellEditingStopped - to name a few - this was the only thing that got it working correctly.

Here's my value parser, for what it's worth:

var codeParser = function (args) {

        var cellEditor = _controller.currentCellEditor.children['codeValue'];
        var paycodeId = +args.colDef.field;
        var paycodeInfo = _controller.paycodes.filter(function (f) { return f.id === paycodeId; })[0];


    // Check against any mask
    if (paycodeInfo && paycodeInfo.mask) {

        var reg = new RegExp("^" + paycodeInfo.mask + '$');
        var match = args.newValue.match(reg);

        if (!match) {
            $mdToast.show($mdToast.simple().textContent('Invalid value - does not match paycode format.').position('top right').toastClass('errorToast'))
                .then(function(r) {
                    _controller.currentCellEditor.children['codeValue'].focus();
                });

            throw 'Invalid value - does not match paycode format.';
        }
    }


    return true;
};

The _controller.currentCellEditor value is set during the init of the cell editor component. I do this so I can then refocus the control after the error has been shown in the toast:

CodeValueEditor.prototype.init = function (params) {

        var form = document.createElement('form');
        form.setAttribute('id', 'mainForm');
        form.setAttribute('name', 'mainForm');


        var input = document.createElement('input');
        input.classList.add('ag-cell-edit-input');
        input.classList.add('paycode-editor');
        input.setAttribute('name', 'codeValue');
        input.setAttribute('id', 'codeValue');
        input.tabIndex = "0"; 
        input.value = params.value;

        if (params.mask) {
            input.setAttribute('data-mask', params.mask);
            input.setAttribute('ng-pattern','/^' + params.mask + '$/');
            input.setAttribute('ng-class',"{'pattern-error': mainForm.codeValue.$error.pattern}");
            input.setAttribute('ng-model', 'ctl.currentValue');
        }

        form.appendChild(input);

        this.container = form;

        $compile(this.container)($scope);
        _controller.currentValue = null;
        // This is crucial - we can then reference the container in
        // the parser later on to refocus the control
        _controller.currentCellEditor = this.container;
        $scope.$digest();

    };

And then cleared in the grid options onCellEditingStopped event:

        onCellEditingStopped: function (event) {
            $scope.$apply(function() {
                _controller.currentCellEditor = null;
            });
        },

I realise it's not specifically for your components (Vue.js) but hopefully it'll help someone else. If anyone has done it a better way, I'm all ears as I don't like throwing the unnecessary exception!

Use Full row editing. Create a global variable like

var problemRow = -1;

Then Subscribe to this events:

 onRowEditingStarted: function (event) {
    if (problemRow!=-1 && event.rowIndex!=problemRow) {
        gridOptions.api.stopEditing();
        gridOptions.api.startEditingCell({
            rowIndex: problemRow,
            colKey: 'the column you want to focus',
        });
    }
},
onRowEditingStopped: function (event) {
    if (problemRow==-1) {
        if (event.data.firstName != "your validation") {
            problemRow = event.rowIndex
            gridOptions.api.startEditingCell({
                rowIndex: problemRow,
                colKey: 'the column you want to focus',
            });
        }
    }
    if (problemRow == event.rowIndex) {
        if (event.data.firstName != "your validation") {
            problemRow = event.rowIndex
            gridOptions.api.startEditingCell({
                rowIndex: problemRow,
                colKey: 'the column you want to focus',
            });
        }
        else{
            problemRow=-1;   
        }

    }
},

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM