Conception et traitement de scripts côté client

  • Rversion finale: Zurich
  • Mis à jour 13 mars 2026
  • 12 minutes de lecture
  • Des scripts clients bien conçus peuvent réduire le temps nécessaire aux utilisateurs pour remplir un formulaire.

    Le traitement approprié côté client dépend d’abord du chargement du formulaire. Effectuer des mises à jour d’enregistrement avant le chargement du formulaire peut produire des résultats inattendus qui contournent le traitement côté client.

    Si vous créez des scripts clients pour contrôler les valeurs de champ sur un formulaire, vous devez utiliser une autre méthode pour contrôler ces valeurs de champ dans une liste. Vous pouvez :
    • Désactiver la modification de liste pour la table.
    • Créez des règles métier ou des contrôles d’accès appropriés pour la modification de liste.
    • Créer des politiques de données.
    • Créez un script client onCellEdit distinct.

    Restreindre la modification des listes

    Si vous créez des politiques d’interface utilisateur ou des scripts clients pour les champs d’un formulaire, vous devez utiliser une autre méthode pour vous assurer que les données de ces champs sont contrôlées de la même manière dans une liste.

    À l’exception des scripts clients onCellEdit, les politiques d’interface utilisateur et les scripts clients ne s’appliquent qu’aux formulaires. Utilisez les méthodes suivantes pour restreindre la modification de liste lors de l’utilisation de scripts clients :
    • Désactiver la modification de liste pour la table.
    • Créez des règles métier ou des contrôles d’accès appropriés pour la modification de liste.
    • Créer des politiques de données.
    • Créez un script client onCellEdit distinct.

    Minimiser les recherches sur le serveur

    Utilisez les données des clients autant que possible pour éliminer le besoin de recherches chronophages sur les serveurs.

    Le scripting client utilise soit des données disponibles sur le client, soit des données récupérées à partir du serveur. Les principaux moyens d’obtenir des informations à partir du serveur sont la recherche GlideAjax g_scratchpad et asynchrone.

    La principale différence entre ces méthodes est que g_scratchpad est envoyée une fois lorsqu’un formulaire est chargé (les informations sont poussées du serveur au client), tandis que GlideAjax est déclenché dynamiquement lorsque le client demande des informations au serveur.

    Remarque :
    GlideRecord et g_form.getReference() sont également disponibles pour récupérer les informations du serveur. Cependant, ces méthodes ne sont plus recommandées en raison de leur impact sur les performances. Les deux méthodes récupèrent tous les champs dans le GlideRecord demandé alors que la plupart des tickets ne nécessitent qu’un seul champ.

    Récupérer les données du serveur à l’aide de g_scratchpad

    L’objet g_scratchpad transmet des informations du serveur au client, par exemple lorsque le client a besoin d’informations non disponibles sur le formulaire.

    Par exemple, si vous avez un script client qui doit accéder au u_retrieve de champ et que le champ n’est pas sur le formulaire, les données ne sont pas disponibles pour le script client. Une solution typique à cette situation consiste à placer le champ sur le formulaire, puis à toujours le masquer avec un script client ou une politique d’interface utilisateur. Bien que cette solution soit plus rapide à configurer, elle est plus lente à exécuter.

    Si vous savez quelles informations le client a besoin du serveur avant le chargement du formulaire, une règle métier d’affichage peut créer des propriétés g_scratchpad pour conserver ces informations. Theg_scratchpad est envoyée au client lors de la demande du formulaire et le rend disponible pour toutes les méthodes de script côté client. C’est un moyen très efficace d’envoyer des informations du serveur au client. Toutefois, vous ne pouvez charger les données de cette façon que lorsque le formulaire est chargé. La règle métier ne peut pas être déclenchée dynamiquement. Dans ce cas, utilisez un appel GlideAjax asynchrone.

    Par exemple, supposons que vous ouvrez un incident et que vous devez transmettre ces informations au client :
    • Valeur de la propriété système css.base.color
    • Indique si l’enregistrement actuel comporte des pièces jointes
    • Le nom du gestionnaire de l’appelant
    Une règle métier d’affichage envoie ces informations au client via le script suivant :
    g_scratchpad.css = gs.getProperty('css.base.color');
    g_scratchpad.hasAttachments = current.hasAttachments();
    g_scratchpad.managerName = current.caller_id.manager.getDisplayValue();
    Pour accéder aux données du bloc-notes à l’aide d’un script client :
    // Check if the form has attachments
    if (g_scratchpad.hasAttachments)
        // do something interesting here
    else
        alert('You need to attach a form signed by ' + g_scratchpad.managerName);

    Récupérer les données du serveur à l’aide de GlideAjax asynchrone

    Le GlideAjax asynchrone vous permet de demander dynamiquement des informations au serveur.

    Ce script compare le groupe de support du CI et le groupe d’affectation de l’incident par nom :
    //Alert if the assignment groups name matches the support group
    function onChange(control, oldValue, newValue, isLoading) {
     
        if (isLoading)
            return;
     
        var ga = new GlideAjax('ciCheck');
     
        ga.addParam('sysparm_name', 'getCiSupportGroup');
        ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
        ga.addParam('sysparm_ag', g_form.getValue('assignment_group'));
        ga.getXML(doAlert); // Always try to use asynchronous (getXML) calls rather than synchronous (getXMLWait)
    }
     
    // Callback function to process the response returned from the server
    function doAlert(response) {
     
        var answer = response.responseXML.documentElement.getAttribute("answer");
     
        alert(answer);
    }
    Ce script s’appuie sur le script include d’accompagnement :
    var ciCheck = Class.create();
     
    ciCheck.prototype = Object.extendsObject(AbstractAjaxProcessor, {
     
        getCiSupportGroup: function() {
     
            var retVal = ''; // Return value
            var ciID   = this.getParameter('sysparm_ci');
            var agID   = this.getParameter('sysparm_ag');		
            var ciRec  = new GlideRecord('cmdb_ci');
     
            // If we can read the record, check if the sys_ids match
            if (ciRec.get(ciID)) {
                if (ciRec.getValue('support_group') == agID)
                    retVal = 'CI support group and assignment group match';
                else
                    retVal = 'CI support group and assignment group do not match';
     
                // Can't read the CI, then they don't match
            } else {
                retVal = 'CI support group and assignment group do not match';
            }
     
            return retVal;
        }
     
    });

    Utiliser le paramètre displayValue setValue() pour les champs de référence

    Lors de l’utilisation de setValue() sur un champ de référence, incluez le paramètre displayValue pour éviter des appels de serveur supplémentaires.

    Lorsque vous utilisez setValue() sur un champ de référence, assurez-vous d’inclure la valeur d’affichage du champ de référence comme 3e paramètre. Si vous définissez la valeur sans displayValue, l’instance effectue un appel synchrone pour récupérer la valeur d’affichage de l’enregistrement que vous avez spécifié. Cet aller-retour supplémentaire vers le serveur peut avoir un impact sur les performances.

    Cet exemple illustre la manière incorrecte d’appeler setValue :
    var id = '5137153cc611227c000bbd1bd8cd2005';
     
    g_form.setValue('assigned_to', id); // Client needs to go back to the server to
                                        // fetch the name that goes with this ID
    Au lieu de cela, incluez la valeur d’affichage comme paramètre facultatif dans setValue() :
    var id = '5137153cc611227c000bbd1bd8cd2005';
    var name = 'Fred Luddy';
     
    g_form.setValue('assigned_to', id, name); // No server call required

    Utiliser une politique d’interface utilisateur au lieu d’un script client

    Dans la mesure du possible, envisagez d’utiliser une politique d’interface utilisateur au lieu d’un script client.

    Les politiques d’interface utilisateur offrent ces avantages par rapport aux scripts clients :
    • Les politiques d’interface utilisateur disposent d’un champ Ordre qui permet un contrôle total sur l’ordre dans lequel les opérations côté client ont lieu.
    • Les politiques d’interface utilisateur n’exigent pas de scripting pour rendre un champ obligatoire, en lecture seule ou visible.
    Remarque :
    Les politiques d’interface utilisateur s’appliquent après les scripts clients.

    Validation de l’entrée à l’aide d’un script client

    Une excellente utilisation d’un script client consiste à valider l’entrée de l’utilisateur.

    Cette validation améliore l’expérience utilisateur, car l’utilisateur découvre s’il existe des problèmes de données avant de soumettre les informations.

    Un exemple de validation consiste à vérifier que la valeur du champ Impact est valide avec la valeur du champ Priorité . Dans cet exemple, l’impact faible n’est pas autorisé avec une priorité élevée.
    if (g_form.getValue('impact') == '3' && g_form.getValue('priority') == '1')
       g_form.showFieldMsg('impact', getMessage('Low impact now allowed with High priority'), 'error');
    

    Définir l’ordre du script client

    Contrôlez l’ordre d’exécution de vos scripts clients à l’aide du champ Ordre. Pour éviter que deux scripts clients ou plus ne s’exécutent simultanément puis entrent en conflit, vous pouvez ajouter un ordre dans lequel les scripts doivent s’exécuter.

    Avant de commencer

    Rôle requis : admin

    Pourquoi et quand exécuter cette tâche

    L’ajout d’une commande au script client crée une séquence de traitement, classée du nombre le plus bas au nombre le plus élevé. Si deux scripts sont en conflit, le script client portant le numéro le plus bas s’exécute en premier.

    Procédure

    1. Accédez à la Tous > Définition du système > Script client et ouvrez un script client existant ou cliquez sur Nouveau.
    2. Configurer la mise en page du formulaire pour inclure le champ Commande .
    3. Ajoutez un numéro au champ de commande en fonction de l’ordre dans lequel vous voulez qu’il s’exécute par rapport à d’autres scripts clients.
      Choisissez un nombre inférieur pour le script que vous souhaitez exécuter en premier.

    Éviter la manipulation DOM

    Évitez si possible la manipulation du modèle d’objet de document (DOM). Cela peut entraîner un problème de maintenabilité lors de la mise à jour des navigateurs.

    Utilisez plutôt l’API GlideForm ou envisagez une approche différente pour la solution. En général, lorsque vous utilisez des méthodes de manipulation DOM, vous devez référencer un élément du DOM par ID ou à l’aide d’un sélecteur CSS. Lors de la référence d’éléments DOM prêts à l’emploi, il existe un risque que l’ID ou le placement de l’élément dans le DOM puisse changer, entraînant ainsi l’arrêt du fonctionnement du code et/ou la génération d’erreurs. Faites preuve de prévoyance, de prudence et comprenez parfaitement le risque que vous courez. Examinez ces objets et réduisez autant que possible l’utilisation des méthodes de manipulation DOM.

    Éviter les scripts clients globaux

    Un script client global est un script client dans lequel la table sélectionnée est globale. Les scripts clients globaux n’ont pas de restrictions de table, ils se chargent donc sur chaque page du système, introduisant un retard de chargement du navigateur dans le processus.

    Il n’y a aucun avantage à charger ce type de scripts sur chaque page.

    Comme alternative, et pour une approche plus modulaire et évolutive, envisagez de déplacer les scripts clients vers une table de base (telle que Tâche[task] ou Élément de configuration[cmdb_ci]) qui peut être dérivée pour toutes les tables enfants/étendues. Le système évite ainsi de charger les scripts sur chaque formulaire de l’interface utilisateur, comme les pages d’accueil ou Catalogue de services, où ils sont rarement (voire jamais) nécessaires.

    Entourer le code dans les fonctions

    Entourez le code d’un script client à l’intérieur d’une fonction.

    Les scripts clients sans fonction entraînent des problèmes avec la portée variable. Lorsque le code n’est pas inclus dans une fonction, les variables et autres objets sont disponibles et partagés avec tous les autres scripts côté client. Si vous utilisez les mêmes noms de variables, il est possible qu’elles entrent en collision. Cela peut entraîner des conséquences inattendues difficiles à résoudre.

    Prenons cet exemple :
    var state = "6";
     
    function onSubmit() {
     
       if(g_form.getValue('incident_state') == state) {
       		alert("This incident is Resolved");
       }
    }
    Étant donné que la variable state n’est pas enfermée dans une fonction, tous les scripts côté client y ont accès. D’autres scripts peuvent également utiliser le nom de variable commun state. Les noms en double peuvent entrer en conflit et entraîner des résultats inattendus. Ces problèmes sont difficiles à isoler et à résoudre. Pour éviter ce problème, assurez-vous que tout le code est encapsulé dans une fonction :
    function onSubmit() {
     
       var state = "6";
     
       if(g_form.getValue('incident_state') == state) {
       		alert("This incident is Resolved");
       }
    }

    Cette solution est beaucoup plus sûre car la portée de l’état de la variable est limitée à la fonction onSubmit(). Par conséquent, la variable d’état n’entre pas en conflit avec les variables d’état des autres scripts côté client.

    Exécuter uniquement les scripts nécessaires

    Pour éviter d’exécuter inutilement des scripts chronophages, assurez-vous que les scripts clients n’effectuent que les tâches nécessaires.

    Les exemples suivants illustrent les améliorations apportées à l’exemple de code initial. Chaque exemple montre une amélioration particulière apportée au script pour améliorer les performances et éviter les appels inutiles.

    N’oubliez pas que les scripts clients n’ont pas de champ Condition . Cela signifie que les scripts onLoad() et onChange() s’exécutent dans leur intégralité chaque fois que le formulaire approprié est chargé. Cet exemple est un script client onChange() inefficace défini pour s’exécuter lorsque le champ Élément de configuration change.

    //Set Assignment Group to CI's support group if assignment group is empty
    function onChange(control, oldValue, newValue, isLoading) {
     
        var ciSupportGroup = g_form.getReference('cmdb_ci').support_group;
     
        if (ciSupportGroup != '' && g_form.getValue('assignment_group) != '')
            g_form.setValue('assignment_group', ciRec.support_group.sys_id);
    }

    Cet exemple améliore le premier en remplaçant la recherche getReference() ou GlideRecord par un appel GlideAjax asynchrone.

    //Set Assignment Group to support group if assignment group is empty
    function onChange(control, oldValue, newValue, isLoading) {
     
        var ga = new GlideAjax('ciCheck');
     
        ga.addParam('sysparm_name', 'getSupportGroup');
        ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
        ga.getXML(setAssignmentGroup);
    }
     
    function setAssignmentGroup(response) {
     
        var answer = response.responseXML.documentElement.getAttribute("answer");
     
        g_form.setValue('assignment_group', answer);
    }

    Le isLoading marqueur est le moyen le plus simple d’empêcher le code inutile d’occuper du temps de navigation dans les scripts onChange. Le isLoading marqueur doit être utilisé au début de tout script qui n’a pas besoin de s’exécuter pendant le chargement du formulaire. Il n’est pas nécessaire d’exécuter ce script sur un chargement de formulaire, car la logique aurait déjà été exécutée lors de la dernière modification du champ. L’ajout de la isLoading vérification au script l’empêche d’effectuer une recherche cmdb_ci à chaque chargement de formulaire.

    Le isTemplate marqueur indique qu’un modèle est en cours de chargement.

    //Set Assignment Group to CI's support group if assignment group is empty
    function onChange(control, oldValue, newValue, isLoading, isTemplate) {
     
        if (isLoading)
            return;
     
        var ga = new GlideAjax('ciCheck');
     
        ga.addParam('sysparm_name', 'getSupportGroup');
        ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
        ga.getXML(setAssignmentGroup);
    }
     
    function setAssignmentGroup(response) {
     
        var answer = response.responseXML.documentElement.getAttribute("answer");
     
        g_form.setValue('assignment_group', answer);
    }
    
    Si le script onChange doit s’exécuter pendant le chargement, utilisez la convention suivante :
    function onChange(control, oldValue, newValue, isLoading, isTemplate) {
     
        if (isLoading) {}; // run during loading
     
        // rest of script here
     
    }
    La vérification newValue indique à ce script de continuer uniquement s’il existe une valeur valide dans le champ approprié. Cela empêche le script de s’exécuter lorsque la valeur de champ est supprimée ou masquée. Cela garantit également qu’il y aura toujours une valeur valide disponible lorsque le reste du script s’exécute.
    //Set Assignment Group to CI's support group if assignment group is empty
    function onChange(control, oldValue, newValue, isLoading, isTemplate) {
     
        if (isLoading)
            return;
     
        if (newValue) {
            var ga = new GlideAjax('ciCheck');
     
            ga.addParam('sysparm_name', 'getSupportGroup');
            ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
            ga.getXML(setAssignmentGroup);
        }
    }
     
    function setAssignmentGroup(response) {
     
       var answer = response.responseXML.documentElement.getAttribute("answer");
     
       g_form.setValue('assignment_group', answer);
    }
    Pour que le script réagisse à une valeur qui change après le chargement du formulaire, utilisez la vérification newValue != oldValue.
    Remarque :
    Cet exemple n’attrape pas les utilisateurs qui modifient une valeur, puis la rétablissent à sa valeur d’origine.
    //Set Assignment Group to CI's support group if assignment group is empty
    function onChange(control, oldValue, newValue, isLoading, isTemplate) {
     
        if (isLoading)
            return;
     
        if (newValue) {
            if (newValue != oldValue) {
                var ga = new GlideAjax('ciCheck');
     
                ga.addParam('sysparm_name', 'getSupportGroup');
                ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
                ga.getXML(setAssignmentGroup);
            }
        }
    }
     
    function setAssignmentGroup(response) {
     
       var answer = response.responseXML.documentElement.getAttribute("answer");
     
       g_form.setValue('assignment_group', answer);
    }
    Dans cet exemple, l’appel GlideAjax est enterré d’un niveau plus profond en réorganisant le script pour vérifier autant de choses disponibles que possible pour le client avant d’exécuter les appels au serveur. Le script vérifie l’affectation avant d’exécuter l’appel GlideAjax. Cela empêche la recherche au serveur lorsque le champ assignment_group est déjà défini.
    //Set Assignment Group to CI's support group if assignment group is empty
    function onChange(control, oldValue, newValue, isLoading, isTemplate) {
     
        if (isLoading)
           return;
     
        if (newValue) {
            if (newValue != oldValue) {
                if (g_form.getValue('assignment_group') == '') {
                    var ga = new GlideAjax('ciCheck');
     
                    ga.addParam('sysparm_name', 'getSupportGroup');
                    ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
                    ga.getXML(setAssignmentGroup);
                }
            }
        }
    }
     
    function setAssignmentGroup(response) {
     
       var answer = response.responseXML.documentElement.getAttribute("answer");
     
       g_form.setValue('assignment_group', answer);
    }