Liaison KnockoutJS lorsque la source est nulle / non définie

Existe-t-il un moyen plus court / plus propre de faire le test null / non défini?

  

Au lieu de

 data-bind="options: SelectedBusinessLine() ? SelectedBusinessLine().Clusters() : [], 

J’aimerais

 data-bind="options: SelectedBusinessLine().Clusters(), 

donner ou prendre le ()

Ou au moins une simple vérification par un opérateur nul ‘??’ SelectedBusinessLine ?? []

Ou un paramètre de liaison à vérifier automatiquement pour une défaillance nulle ou silencieuse.

Des idées si cela est possible?

Cette page propose plusieurs solutions. La partie pertinente est celle-ci:

Protection contre les objects nuls

Si vous avez une observable qui contient un object et que vous souhaitez lier les propriétés de cet object, vous devez faire attention s’il y a une chance qu’il soit nul ou non défini. Vous pouvez écrire votre liaison comme:

  

Il y a plusieurs façons de gérer celle-ci. La méthode préférée serait d’utiliser simplement la liaison de modèle:

 var viewModel = { items: ko.observableArray(), selectedItem: ko.observable() }; 

    Avec cette méthode, si selectedItem est nul, cela ne rendra rien. Donc, vous ne verriez pas l’inconnu comme vous l’auriez dans la reliure originale. Cependant, il présente l’avantage supplémentaire de simplifier vos liaisons, car vous pouvez désormais simplement spécifier vos noms de propriété directement plutôt que selectedItem().name . C’est la solution la plus simple.

    Juste pour explorer certaines options, voici quelques alternatives:

    Vous pouvez utiliser une observable calculée, comme nous l’avons fait auparavant.

     viewModel.selectedItemName = ko.computed(function() { var selected = this.selected(); return selected ? selected.name() : 'unknown'; }, viewModel); 

    Cependant, ceci ajoute encore un peu de ballonnement à notre modèle de vue que nous ne souhaitons peut-être pas et nous pourrions devoir répéter ceci pour beaucoup de propriétés.

    Vous pouvez utiliser une liaison personnalisée comme:

     
    ko.bindingHandlers.safeText = { update: function(element, valueAccessor, allBindingsAccessor) { var options = ko.utils.unwrapObservable(valueAccessor()), value = ko.utils.unwrapObservable(options.value), property = ko.utils.unwrapObservable(options.property), fallback = ko.utils.unwrapObservable(options.default) || "", text; text = value ? (options.property ? value[property] : value) : fallback; ko.bindingHandlers.text.update(element, function() { return text; }); } };

    Est-ce mieux que l’original? Je dirais probablement pas. Cela évite le JavaScript dans notre liaison, mais il est encore assez verbeux.

    Une autre option serait de créer une observable augmentée qui offre un moyen sûr d’accéder aux propriétés tout en permettant à la valeur réelle d’être nulle. Pourrait ressembler à:

     ko.safeObservable = function(initialValue) { var result = ko.observable(initialValue); result.safe = ko.dependentObservable(function() { return result() || {}; }); return result; }; 

    Donc, ceci est juste une observable qui expose également une observable calculée nommée safe qui renverra toujours un object vide, mais l’observable réelle peut continuer à stocker null.

    Maintenant, vous pouvez vous y connecter comme:

     

    Vous ne verriez pas la valeur inconnue quand elle est nulle, mais au moins elle ne provoquerait pas d’erreur lorsque selectedItem est nul.

    Je pense que l’option préférée serait d’utiliser la liaison de modèle dans ce cas, surtout si vous avez plusieurs de ces propriétés à lier.

    Une manière non mentionnée dans l’ excellente page référencée par une autre réponse est d’utiliser with

     

    Toute l’interface utilisateur disparaîtra si l’ selecteditem est NULL.

    Le “Avec” fonctionne (probablement les autres fonctionnent aussi …)

    Mais avec “With”, l’interface utilisateur du rôle disparaît / apparaît même s’il y a des conditions à l’intérieur … Par exemple … Je dois définir un bouton Status (true / false), mais uniquement si Status n’est pas nul. .

       Desativar   Ativar   

    Cela marche. Dans ce cas.

    Mais parfois, le “Avec” fonctionne comme Simon_Weaver a dit!

    Je préfère cette méthode

    Créer une liaison personnalisée

     ko.bindingHandlers.safeText = { update: function (element, valueAccessor, allBindingsAccessor) { try { var tryGetValue = valueAccessor()(); ko.bindingHandlers.text.update(element, valueAccessor()); } catch (e) { ko.bindingHandlers.text.update(element, function () { return ""; }); } } }; 

    Usage

     data-bind="safeText: function() { return my().nested.object.property; } 

    La seule chose que vous devez append est d’emballer votre valeur originale avec ‘function () {return …}’

    Cela arrêtera cependant toutes les erreurs sous l’appel de valeur. Vous pouvez améliorer la liaison personnalisée en recherchant uniquement les exceptions «non définies». Vous pouvez également améliorer cette liaison en ajoutant une option de texte par défaut.

    La plupart de ces solutions ne fonctionnent pas dans un certain cas pour moi, où je mets un atsortingbut:

     
    ...

    Le template et les liaisons ne fonctionneraient pas ici, car si je n’avais pas de descendant actif, mon div serait vide. Pour ma solution, j’ai créé une méthode observable:

     ko.observable.fn.get = function (propertyName, defaultValue) { var self = this(), propertyValue; if (self != null) { propertyValue = ko.unwrap(self[propertyName]); } return propertyValue || defaultValue; } 

    Ce qui me permet de changer ma liaison à ceci:

     
    ...

    La plupart des solutions ci-dessus n’ont pas fonctionné pour moi, car je voulais seulement appliquer cela à un seul élément dans un foreach . J’ai donc modifié l’approche de la réponse acceptée: