2 votes

Comment empêcher la fermeture du mode d'édition des cellules en cas d'erreur de validation avec des composants Vue personnalisés dans une grille d'agitation ?

J'ai réussi à rendre mon propre composant en tant que cellEditor et j'aimerais qu'il essaie de valider la valeur et qu'il empêche la fermeture s'il échoue.

Si je regarde este puis https://www.ag-grid.com/javascript-grid-cell-editing/#editing-api il y a des fonctions de rappel annulables pour l'édition. Mais dans cette fonction de rappel, y a-t-il un moyen d'accéder au composant actuellement instancié ? Je pense que ce serait le moyen le plus simple de gérer cela.

J'utilise vee-validate, donc la fonction de validation est asynchrone, juste pour garder à l'esprit.

2voto

PoorbandTony Points 26

J'ai eu un problème similaire - bien qu'en AngularJS et en mode non-Angular pour ag-grid - j'avais besoin d'empêcher la navigation lorsque l'éditeur de cellules ne passait pas la validation.

La documentation n'étant pas très détaillée, j'ai fini par ajouter un éditeur de cellules personnalisé avec un formulaire enveloppant le champ de saisie (pour gérer les détails tels que la mise en évidence en rouge, etc. Cela m'a permis d'aller jusqu'ici, mais la partie cruciale était d'essayer d'empêcher l'utilisateur de sortir ou de s'éloigner lorsque la valeur n'était pas valide, afin qu'il puisse au moins corriger le problème.

Pour ce faire, j'ai ajouté un analyseur de valeur lors de l'ajout de la cellule, puis, si la valeur n'est pas valide selon diverses règles, j'ai lancé une exception. Ce n'est pas idéal, je sais, mais cela fait empêcher l'ag-grid d'essayer de s'éloigner de la cellule.

J'ai essayé de nombreuses approches pour résoudre ce problème - en utilisant la fonction tabToNextCell événements, suppressKeyboardEvent , navigateToNextCell , onCellEditingStopped - pour n'en citer que quelques-uns - c'est la seule chose qui a permis de le faire fonctionner correctement.

Voici mon analyseur de valeurs, pour ce qu'il vaut :

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;
};

Le site _controller.currentCellEditor est définie lors de l'init du composant éditeur de cellules. Je fais cela pour pouvoir recentrer le contrôle après l'affichage de l'erreur dans le 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();

    };

Et ensuite dégagé dans les options de la grille onCellEditingStopped événement :

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

Je réalise que ce n'est pas spécifiquement pour vos composants (Vue.js) mais j'espère que cela aidera quelqu'un d'autre. Si quelqu'un a trouvé une meilleure solution, je suis tout ouïe car je n'aime pas lancer une exception inutile !

2voto

Idan Marko Points 54

Utilisez l'édition de la ligne complète. Créez une variable globale comme

var problemRow = -1;

Alors, inscrivez-vous à cet événement :

 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;   
        }

    }
},

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X