J'ai une grille Kendo UI ASP.NET MVC avec des opérations CRUD qui est soumise dans le cadre d'un formulaire. Dans l'extrait de code suivant, j'essaie d'afficher une colonne avec une liste déroulante modifiable en ligne (liée aux noms d'utilisateur et aux ID) qui affiche le nom d'un utilisateur mais a une valeur de l'ID de l'utilisateur.

Envoie le formulaire correctement, mais affiche les ID utilisateur plutôt que les noms:

columns.ForeignKey(p => p.UserId, (System.Collections.IEnumerable)ViewBag.Users, "SystemUserId", "Name").Title("User").EditorTemplateName("ComboBoxInForm").Visible(true).ClientTemplate("#= UserId #" +
"<input type='hidden' name='Users[#= index(data) #].UserId' value='#= UserId #' />"
);

ComboBoxInForm EditorTemplate:

@model object 
@(
 Html.Kendo().ComboBoxFor(m => m)
 .BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)

Si je supprime le ClientTemplate qui fournit la balise d'entrée de formulaire, le nom de l'utilisateur est ce qui est affiché plutôt que la valeur de l'ID de l'utilisateur qui est ce que je veux. Cependant, je dois le soumettre par lots dans le cadre d'un formulaire, je ne peux donc pas supprimer la balise d'entrée du formulaire.

Échec de l'envoi du formulaire (pas de balise d'entrée), mais affiche correctement les noms d'utilisateur plutôt que les ID:

columns.ForeignKey(p => p.UserId, (System.Collections.IEnumerable)ViewBag.Users, "SystemUserId", "Name").Title("User").EditorTemplateName("ComboBoxInForm").Visible(true);

Quelle solution puis-je utiliser pour combiner ces deux exigences afin que la colonne de la grille affiche les noms (mais avec des valeurs d'ID) et fournit également la balise d'entrée de formulaire?

0
Collin M. Barrett 6 avril 2017 à 20:52

2 réponses

Meilleure réponse

Tout d'abord, le ClientTemplate ne remplace pas le EditorTemplate ...

Le ClientTemplate est essentiellement le modèle display et le EditorTemplate est, eh bien, le modèle editor .

Donc, ce que vous voulez que le ClientTemplate fasse est d'afficher le nom associé à UserId.

Si vous souhaitez conserver la grille telle que vous l'avez (en utilisant ForeignKey et les champs masqués), vous devez ajouter une fonction de "mappage" qui mappe le UserId sélectionné par la liste déroulante au nom associé.

Vous pouvez le faire comme ceci:

Rasoir:

.ClientTemplate("#= mapIdToName(UserId) #" +
    "<input type='hidden' name='Users[#= index(data) #].UserId' value='#= UserId #' />");

Javascript:

function mapIdToName(id) {
    var grid = $("#grid").getKendoGrid(),
        users = grid.options.columns[0].values,
        name;

    for (var i = 0; i < users.length; i++) {
        if (users[i].value == id) {
            name = users[i].text;
            break;
        }
    }

    return name;
}

Cela utilise le tableau Id-Name que vous avez déjà (via grid.options.columns.values) qui a été créé par la méthode ForeignKey ().

Solutions alternatives . . . . . Cependant, il existe d'autres moyens de réaliser ce que vous voulez.

Une méthode consiste à ne pas utiliser de ForeignKey et à lier à la place la colonne à un objet qui contient à la fois l'ID et le nom et le EditorTemplate plus spécifique se lie à la même collection que ForeignKey (). Cela ne nécessite pas la fonction de mappage, c'est-à-dire:

Rasoir:

columns.Bound(x => x.User)
    .ClientTemplate("#= User.Name #" +
    "<input type='hidden' name='Users[#= index(data) #].UserId' value='#= UserId #' />");

EditorTemplate:

@model object
@(
 Html.Kendo().ComboBoxFor(m => m)
 .DataValueField("SystemUserId")
    .DataTextField("Name")
    .BindTo((System.Collections.IEnumerable)ViewBag.Users)
)

Solutions alternatives . . . . . Cependant, il existe d'autres moyens de réaliser ce que vous voulez....

Une troisième façon (c'est ainsi que je fais les choses) est de ne pas utiliser du tout les entrées cachées. Au lieu de cela, je poste les données manuellement avec un appel ajax où je sérialise d'abord les données du formulaire «principal» (pas les données de la grille) dans un objet (c'est super facile si vous utilisez kendo MVVM), puis je fusionne les données de grille modifiées avec le formulaire data (en utilisant extend), puis publiez l'objet combiné résultant.

L'inconvénient de la méthode de saisie masquée est que vous devez limiter la grille à un petit nombre de lignes car la technique ne pourra publier que la valeur d'une seule page de données car les données des pages 2, 3, etc. ne sont pas rendues et ont donc pas d'entrées cachées dans le formulaire à inclure dans le message....

Les avantages de ceci sont qu'il prend en charge des ensembles de données plus volumineux car il peut utiliser le mécanisme de pagination de la grille et (c'est la raison principale pour laquelle j'aime cette technique) en soumettant le formulaire / en-tête / données parentes avec toutes les données de la grille / enfant (nouveau / mis à jour / supprimé) en une seule requête, vous pouvez traiter toutes les données en même temps sur le serveur, ce qui permet une meilleure validation de l'ensemble de «l'image» des données et permet aux mises à jour de se produire dans une seule tranche de transaction.

1
The Dread Pirate Stephen 6 avril 2017 à 20:18

Une autre réponse des forums Telerik.

La raison de ce comportement est que le générateur ForeignKey propose l'affichage du texte associé à la valeur numérique en tant que fonctionnalité intégrée. Sous le capot, la colonne est liée au champ qui contient uniquement une valeur numérique. Afin d'afficher la représentation textuelle dans votre modèle client, une logique personnalisée doit être écrite. Je donnerais quelques directives sur la façon d'y parvenir au cas où cela pourrait être utile pour d'autres personnes confrontées aux mêmes difficultés:

  1. La valeur de l'élément d'entrée peut être définie comme une fonction qui accepte la valeur de champ réelle comme premier paramètre et le nom de champ (texte statique) comme deuxième paramètre.
  2. Les wrappers Telerik MVC rendent le HTML et le JavaScript nécessaires pour initialiser un widget d'interface utilisateur Kendo. Chaque colonne de clé étrangère est simplement un tableau de paires clé-valeur stockées dans columns.values.
  3. Voici un corps de fonction avec quelques commentaires qui devraient vous aider à illustrer une idée simple de recherche du texte à partir du columns.values associé à un nombre spécifique (valeur de champ actuelle):

    function textValue(value, fieldName) {
      // $("#gridNameId").data("kendoGrid").options.columns contains the
      // columns defined in the grid's configuration
    
      // iterate through the array and check the .field value of each column to find
      // a column field with same name as the field name parameter (second parameter)
    
      // each column which is defined as "foreign key" does have values array. 
      // It contains key-value pairs of each values displayed in the combo box.
    
      // return the text value associated with same value as the first first argument (value)
      // return text associated with the value
    }
    
    ClientTemplate("#= ProductID #" +
    "<input type='hidden' name='Products[#= index(data)#].ProductID' value='#= textValue(data.ProductID, \'ProductID\') #' />"
    
0
CarenRose 27 févr. 2019 à 23:35