Mise en place de composants Telerik en MVC3
Synopsis
Date de publication : 12/07/2011. Date de mise à jour : 12/07/2011.
Par
Julien Brasselet
0. Introduction
I. Diagramme UML
II. La couche d'accès aux données
III. Rappel sur MVC
III-A. Présentation générale
III-B. Le modèle
III-C. La vue
III-D. Le contrôleur
IV. Le moteur Razor
IV-A. Présentation
IV-B. Quelques exemples
V. Création d'une solution MVC3 Telerik
V-A. Télécharger le composant Telerik
V-B. Créer une solution Telerik
V-C. Description de la solution
V-D. Création du modèle
VI. Quelques composants Telerik
VI-A. Le calendrier
VI-A-1. Définition du calendrier
VI-A-2. Action sur une sélection
VI-A-3. La date Picker
VI-B. Le combo box
VI-B-1. Le combo box classique
VI-B-2. La liste déroulante
VII. La grille Télérik
VII-A. Data binding
VII-A-1. Serveur
VII-A-2. Ajax
VII-B. Paging and Sorting
VII-C. Filtre et Groupe
VII-D. CRUD
VII-E. Objets complexes
VII-F. Templates d'affichage
VII-F-1. Templates serveur
VII-F-2. Templates client
VII-F-3. Les fonctions de mise à jour
VII-F-4. Aller plus loin
VIII. Conclusion
IX. Liens
0. Introduction
L'architecture MVC (Modèle-Vue-Controleur) permet une nette séparation des concepts d'interface, des données et de la logique de contrôle d'une application Web.
Dans ce but, Microsoft a développé son propre framework MVC. Ce dernier a évolué au fil des années. La version MVC3 a apporté son lot de nouveauté avec principalement un nouveau moteur de rendu appelé Razor.
En parallèle, Telerik avait développé des composants utilisables aisément en ASP.Net Ajax. Telerik met également à disposition des composants utilisables avec le modèle MVC3 tels des grilles, des menus ou des onglets. Ces composants permettent un développement plus rapide et fournissent une interface agréable pour le développeur et l'utilisateur.
Cet article montrera comment implémenter certains de ses composants dans une solution MVC assez simple.
I. Diagramme UML
Nous partirons sur une modèle assez simple représentant une application de gestion de formations.
NB : Ce modèle n'est ni complet ni optimal. Il est juste là pour servir de base aux interfaces.
II. La couche d'accès aux données
La couche d'accès aux données a été codée afin de conserver les modifications en mémoire tant que l'on ne change pas de page.
Cette couche se base sur des DTO et des factory.
III. Rappel sur MVC
III-A. Présentation générale
L'architecture MVC oblige à la séparation des couches de l'application, ce qui en fait une base solide pour le développement et donc une très bonne pratique.
Cette architecture peut être représentée ainsi.
III-B. Le modèle
Le modèle est la représentation du comportement de l'application. Ses responsabilités sont la gestion des traitements des données ainsi que l'accès à la base de données. Il doit garantir l'intégrité des données.
Il ne doit en aucun cas gérer la présentation des données.
III-C. La vue
La vue est souvent l'interface utilisateur. Elle ajoute une couche dite de présentation aux données afin de les rendre plus lisible et aisément manipulable. Cette dernière action est très souvent liée au contrôleur.
Elle ne doit en aucun cas effectuer de traitement sur les données.
III-D. Le contrôleur
Le contrôleur va recevoir les actions effectuées sur la vue. Il va lancer les différentes actions liées à l'action réalisées dans la vue.
Si les données doivent être modifiées, il fera appel au modèle pour lancer le traitement adéquat. Si la vue doit être modifiée, il le lui signifiera.
IV. Le moteur Razor
IV-A. Présentation
Razor est un nouveau moteur de rendu utilisé dans le cadre d'ASP.Net MVC3. Il est toujours possible d'utiliser l'ancien moteur ASP.Net. Néanmoins ce nouveau moteur est, à mon sens, indiscutablement plus lisible et pratique à utiliser.
Ce moteur a été développé afin :
- De limiter les caractères séparant le code serveur du code HTML,
- D'être facile à apprendre,
- D'améliorer l'intellisense,
- D'être facilement testable.
Le blog de Scott Guthrie (http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx) explique plus en détail les nouveautés de ce moteur et son utilisation. Je vais juste reprendre quelques exemples rapides pour cet article.
IV-B. Quelques exemples
Pour commencer, le moteur razor s'appuie essentiellement sur le caractère @ et le HTML.
Voici un comparatif d'un simple code affichant la date du jour
Moteur ASP.N
et
|
Moteur
Razor
|
<
h2
>
<%
:
DateTime
.Now
%>
</
h2
>
|
<
h2
>
@
DateTime
.Now
</
h2
>
|
Le moteur Razor sait déterminer la fin d'une variable et passer de nouveau à l'interprétation du code HTML. Cet exemple simple n'est pas des plus parlant mais imaginons une liste affichant un identifiant et un libellé. Les codes suivants montrent bien la différence de lisibilité des deux moteurs :
Moteur ASP.N
et
|
Moteur
Razor
|
<
ul
id
="
maliste
">
<%
foreach
(
var
p
in
ViewBag.liste
)
{
%>
<
li
>
<%
=
p.identifiant
%>
-
<%
=
p.libelle
%>
</
li
>
<%
}
%>
</
ul
>
|
<
ul
id
="
maliste
">
@
foreach
(
var
p
in
ViewBag.liste
)
{
<
li
>
@
p.identifiant
-
@
p.libelle
</
li
>
}
</
ul
>
|
Le blog de Scott Guthrie montre également l'utilisation de bloc de code, l'intelligence si jamais une adresse email est rencontrée (et le caractère @ non pris en compte)
Nous ne nous attarderons pas plus sur la syntaxe Razor ici-même.
V. Création d'une solution MVC3 Telerik
V-A. Télécharger le composant Telerik
La dll Telerik pour les composats MVC est téléchargeable ici (via un msi) :
http://www.telerik.com/products/aspnet-mvc.aspx
NB : Il est nécessaire de se créer un compte sur le site Telerik.
Il faut ensuite installer le msi téléchargé.
V-B. Créer une solution Telerik
Ouvrir un nouveau projet Telerik MVC3 Web Application (Razor)
Le wizard Telerik se lance alors
NB : Telerik propose plusieurs skins de base.
V-C. Description de la solution
La solution est composée initialement de plusieurs dossiers dont trois primordiaux représentant les vues, le modèle et les contrôleurs.
V-D. Création du modèle
Par simplicité, aucune base de données ne sera utilisée dans les sources. Les fonctions ramèneront juste des listes enregistrées en session.
Nous allons maintenant créer des vues afin de tester les différents composants Telerik.
VI. Quelques composants Telerik
VI-A. Le calendrier
VI-A-1. Définition du calendrier
Le contrôle calendrier est réellement très simple à utiliser.
Nous y noterons 3 caractéristiques principales :
- Une date courante
- Une date minimale
- Une date Maximale
Voici comment le définir dans la vue
Définition d'un composant Calendar Telerik avec le moteur Razor |
@(Html.Telerik().Calendar()
.Name("Calendar")
.Value((DateTime)ViewData["selectedDate"])
.MinDate((DateTime)ViewData["minDate"])
.MaxDate((DateTime)ViewData["maxDate"])
)
|
Il suffit dans le contrôleur de remplir les variables du ViewData (ici entre le 8juin 2011 et le 15 aout 2012) pour obtenir un beau calendrier
VI-A-2. Action sur une sélection
Il est également possible de réaliser une action sur la sélection d'une date.
other |
@(Html.Telerik().Calendar()
.Name("Calendar")
.Selection(settings => settings
.Action("SelectAction", new { date="{0}"})
.Dates(
new List<DateTime> {
DateTime.Today.AddDays(-1),
DateTime.Today.AddDays(2),
DateTime.Today.AddDays(3),
}
)
)
)
|
Un attribut action a été ajouté en définissant le paramètre à envoyer. Il est suivit d'un attribut Dates qui limite ne nombre de date soumise à cette action.
VI-A-3. La date Picker
Il est possible de vouloir un bouton permettant d'afficher le calendrier. Pour cela il faut utiliser le Date Picker dont voici un exemple de code
other |
@(Html.Telerik().DatePicker()
.Name("DatePicker")
.HtmlAttributes(new { id = "DatePicker_wrapper" })
.Min((DateTime)ViewData["minDate"])
.Max((DateTime)ViewData["maxDate"])
.ShowButton(true)
.Value((DateTime)ViewData["selectedDate"])
)
|
Ceci nous donne le rendu suivant :
VI-B. Le combo box
VI-B-1. Le combo box classique
Nous allons ici afficher la liste des formations dans un combo box.
La première chose à faire est de passer à la vue le modèle que nous utiliserons. Cela s'effectue bien entendu dans le contrôleur
other |
public ActionResult Index()
{
return View(GestFormat.Models.FormationFactory.SelectAll().ToList());
}
|
Coté IHM, le code razor est des plus simplistes :
other |
@(Html.Telerik().ComboBox()
.Name("ComboBox")
.BindTo(new SelectList(Model, "Identifiant", "Libelle"))
.Filterable(filtering => { filtering.FilterMode(AutoCompleteFilterMode.StartsWith);})
.Effects(fx=>fx.Slide()
.Opacity()
.OpenDuration(500)
.CloseDuration(200)
)
)
|
L'attribut Filterable permet de proposer les éléments commençant par le texte taper dans l'input (dans cet exemple) Il peut également être configuré avec l'option Contains.
La propriété Effects permet de gérer les effets d'affichage de la liste des éléments (toggle/slide, opacité, temps d'ouverture et de fermeture)
VI-B-2. La liste déroulante
Les différences entre la liste déroulante et le combo box. Il n'est pas possible d'effectuer de saisie dans la liste déroulante et son aspect est différent.
Coté code, nous retrouvons la même structure
other |
@(Html.Telerik().DropDownList()
.Name("DropDownList")
.BindTo(new SelectList(Model, "Identifiant", "Libelle"))
.Effects(fx=>fx.Slide()
.Opacity()
.OpenDuration(500)
.CloseDuration(200)
)
)
|
VII. La grille Télérik
Un des composants les plus demandé en Web est le GridView. Ce composant est souvent la source de bien des soucis et de développement spécifique.
La grille Telerik propose d'innombrables possibilités :
- Binding server / client / webservices
- Tri / Filtre / Pagination
- Agrégation
- Templates
Cette liste est loin d'être exhaustive. Nous verrons quelques options dans ce paragraphe. Le site de Telerik et l'installation du framework MVC propose d'autres exemples plus complexes.
VII-A. Data binding
VII-A-1. Serveur
Nous allons commencer ici par binder les données coté serveur. Nous afficherons les données des sessions de formations.
Pour commencer, nous passerons la liste des sessions de formation à la vue via le contrôleur.
other |
public ActionResult Index()
{
return View(GestFormat.Models. FormateurFactory.SelectAll());
}
|
Nous pouvons maintenant créer notre grille
other |
@model List<GestFormat.Models.FormateurDto>
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(o => o.Identifiant).Width(100);
columns.Bound(o => o.Nom).Width(200);
columns.Bound(o => o.Prenom).Width(200);
columns.Bound(o => o.Inscription).Format("{0:dd/MM/yyyy}").Width(120);
})
.DataBinding(dataBinding =>
{
dataBinding.Server().Select("Index", "Grid");
}
)
.Footer(true)
)
|
Voici le rendu de notre grille binder coté serveur (qui ne nous aura pas demandé beaucoup d'effort)
VII-A-2. Ajax
Le principe est le même pour le binding coté Ajax. Les modifications nécessaire se situe coté contrôleur avec l'ajout d'un attribut devant la fonction de chargement ainsi qu'un léger changement dans le passage du model.
other |
public ActionResult Index()
{
return View();
}
[GridAction]
public ActionResult _Index()
{
return View(new GridModel(GestFormat.Models.FormateurFactory.SelectAll()));
}
|
Coté interface, le seul changement est d'indiquer à la grille qu'elle sera binder en ajax
other |
@model List<GestFormat.Models.FormateurDto>
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(o => o.Identifiant).Width(100);
columns.Bound(o => o.Nom).Width(200);
columns.Bound(o => o.Prenom).Width(200);
columns.Bound(o => o.Inscription).Format("{0:dd/MM/yyyy}").Width(120);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax().Select("_Index", "Grid");
}
)
.Footer(true)
)
|
Le rendu est exactement le même.
Nous réaliserons la suite du TP avec un databinding ajax.
VII-B. Paging and Sorting
Afin de gérer les fonctions de tri et de pagination, il n'est pas nécessaire de modifier son code au niveau du model ou du contrôleur. Seule la vue se verra modifiée et très peu.
En effet il suffit d'ajouter les attributs Sortable et Pageable à la définition de la grille.
other |
@(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns => {...})
.DataBinding(dataBinding => {...})
.Pageable()
.Sortable()
.Footer(true)
)
|
VII-C. Filtre et Groupe
Il existe également une fonctionnalité simple afin de filtrer les données. Les modifications sont encore une fois uniquement coté interface.
other |
@(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns => {...})
.DataBinding(dataBinding => {...})
.Filterable()
.Footer(true)
)
|
Il est enfin possible de gérer des groupes de données en déplaçant les colonnes dans le header.
other |
@(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns => {...})
.DataBinding(dataBinding => {...})
.Filterable()
.Groupable()
.Footer(true)
)
|
VII-D. CRUD
L'intérêt des grilles, outre la présentation des données, est de pouvoir réaliser des modifications sur les données sans passer par une page intermédiaire. Nous allons voir ici comment réaliser les opérations élémentaires de modification, ajout et suppression des données.
Il existe plusieurs modes pour la création et l'édition des données :
- In-line : modification directement dans la grille
- Pop-up : affichage d'un pop-up pour la modification
- In-Form : affichage d'un formulaire dans la grille
Nous prendrons le cas d'une modification in-line.
NB : L'aspect des formulaires des opérations Pop-up et In-Form dépendra entre autres de vos Data Annotations. Pensez-y !
Plusieurs paramètres sont nécessaires dans la définition de la grille. Avant tout, il est indispensable de déterminer la DataKey, soit la clé de votre table. Pour cela, la grille possède une propriété DataKeys dont voici un exemple :
other |
@(Html.Telerik().Grid(Model)
.Name("Grid")
.DataKeys(keys => { keys.Add(p => p.Identifiant); })
...
|
Il faut ensuite implémenter le bouton d'ajout d'une nouvelle instance :
|
.ToolBar(commands => commands.Insert().ButtonType(GridButtonType.Image).ImageHtmlAttributes(new { style = "margin-left:0" }))
|
- Il existe plusieurs types de bouton (GridButtonType) :BareImageImageImageAndTextText
Il faut ensuite ajouter les boutons d'édition et de suppression
other |
.Columns(columns =>
{
columns.Command(commands => { commands.Edit().ButtonType(GridButtonType.Image); commands.Delete().ButtonType(GridButtonType.Image); }).Width(100).Title("Commands");
columns.Bound(o => o.Identifiant);
...
|
Il ne faut pas oublier de changer le binding afin de référencer les fonctions d'ajout, modification et suppression
other |
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("_Index", "Grid")
.Insert("_Insert", "Grid")
.Update("_Update", "Grid")
.Delete("_Delete", "Grid"); ;
}
)
|
Enfin, il faut définir le mode d'édition de la grille
|
.Editable(editing => editing.Mode(GridEditMode.InLine))
|
Voici un exemple de fonctions gérant les CRUD dans le contrôleur.
other |
[GridAction]
public ActionResult _Insert()
{
Models.FormateurDto dto = new Models.FormateurDto();
if (TryUpdateModel(dto))
{
Models.FormateurFactory.Insert(dto);
}
return View(new GridModel(Models.FormateurFactory.SelectAll()));
}
[GridAction]
public ActionResult _Update(int id)
{
Models.FormateurDto dto = new Models.FormateurDto { Identifiant = id };
if (TryUpdateModel(dto))
{
Models.FormateurFactory.Update(dto);
}
return View(new GridModel(Models.FormateurFactory.SelectAll()));
}
[GridAction]
public ActionResult _Delete(int id)
{
Models.FormateurDto dto = Models.FormateurFactory.Search(id);
if (dto != null)
{
Models.FormateurFactory.Delete(dto);
}
return View(new GridModel(Models.FormateurFactory.SelectAll()));
}
|
VII-E. Objets complexes
Essayons maintenant d'afficher une grille avec par exemple nos sessions de formations. Les sessions contiennent des liens vers les formateurs, les formations et les salles.
Le code cshtml contient le code suivant
other |
@model List<GestFormat.Models.SessionFormationDto>
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@(Html.Telerik().Grid(Model)
.Name("Grid")
.DataKeys(keys => { keys.Add(p => p.Identifiant); })
.ToolBar(commands => commands.Insert().ButtonType(GridButtonType.Image).ImageHtmlAttributes(new { style = "margin-left:0" }))
.Columns(columns =>
{
columns.Command(commands => { commands.Edit().ButtonType(GridButtonType.Image); commands.Delete().ButtonType(GridButtonType.Image); }).Width(100).Title("Commands");
columns.Bound(o => o.Identifiant);
columns.Bound(o => o.Formation.Libelle).Width(200);
columns.Bound(o => o.Formateur.Nom).Width(200);
columns.Bound(o => o.Formateur.Prenom).Width(200);
columns.Bound(o => o.Salle.Numero).Width(80);
columns.Bound(o => o.DebutSession).Format("{0:dd/MM/yyyy}").Width(120);
columns.Bound(o => o.FinSession).Format("{0:dd/MM/yyyy}").Width(120);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("_Index", "GridTemplate")
.Insert("_Insert", "GridTemplate")
.Update("_Update", "GridTemplate")
.Delete("_Delete", "GridTemplate"); ;
}
)
.Editable(editing => editing.Mode(GridEditMode.PopUp))
.Pageable()
.Sortable()
.Footer(true)
)
|
A remarquer que je suis passé en mode de modification pop-up.
Notre grille a donc l'aspect suivant
Nous désirons ajouter une nouvelle session
Seuls les champs « simples » de notre dto apparaissent à l'écran. L'intérêt est donc limité.
De même, dans le mode inline, notre interface de modification aura cette allure
Il serait préférable d'avoir une liste déroulante permettant de choisir le formateur et le numéro de la salle.
Pour combler ses « manques », nous allons utiliser des templates d'affichage.
VII-F. Templates d'affichage
Il est possible d'effectuer des templates coté serveur ou coté client. Ici nous afficherons la liste des formateurs à la place des colonnes Nom et Prénom.
VII-F-1. Templates serveur
Pour créer un template de modification, plusieurs étapes vont être nécessaires :
- Ajouter un attribut au DTO de session,
- Remplir une structure de données contenant la liste des formateurs,
- Créer un fichier de template d'affichage et un d'édition.
Nous allons tout d'abord ajouter un attribut à notre formateurDto contenu dans notre sessionDto :
other |
public class SessionFormationDto
{
[ScaffoldColumn(false)]
public Int32? Identifiant { get; set; }
[DisplayName("Formation")]
public FormationDto Formation { get; set; }
[DisplayName("Salle")]
public SalleDto Salle { get; set; }
[DisplayName("Formateur"), UIHint("ListeFormateur")]
public FormateurDto Formateur { get; set; }
[DisplayName("Début")]
[DataType(DataType.Date)]
public DateTime DebutSession { get; set; }
[DisplayName("Fin")]
[DataType(DataType.Date)]
public DateTime FinSession { get; set; }
}
|
L'attribut en question est le UIHint. Cet attribut indique qu'il faut utiliser des templates ayant pour nom ListeFormateur.
Nous allons ensuite mettre la liste des formateurs dans le ViewData. Ici la fonction ramène des FormateurDto contenant l'identifiant et la concaténation du nom et du prénom dans le nom.
other |
public ActionResult _Index()
{
ViewData["Formateurs"] = Models.FormateurFactory.SelectAllForDdl();
return View(new GridModel(Models.SessionFormationFactory.SelectAll()));
}
|
NB : Cette affectation devra être effectuée dans toutes les fonctions renvoyant la vue (insert, update, delete, etc.)
Ensuite, nous allons créer les templates d'affichage et d'édition. Pour cela il est nécessaire de créer dans le répertoire de la vue des répertoires appelés DisplayTemplates et EditorTemplates.
Nous allons désormais créer les templates.
Le template d'affichage sera très simple. Nous allons afficher le prénom du formateur suivi de son nom. Nous avons vu que notre fichier template devra porter le nom de ListeFormateur. Il devra aussi avoir une extension cshtml. Sa structure sera très simple :
other |
@model GestFormat.Models.FormateurDto
@Model.Prenom @Model.Nom
|
Le template d'édition se basera sur une simple liste déroulante.
other |
@(Html.Telerik().DropDownList()
.Name("LeFormateur")
.BindTo(new SelectList((IEnumerable)ViewData["Formateurs"], "Identifiant", "Nom"))
)
|
Enfin nous allons modifier notre vue. La modification sera très simple. AU lieu d'afficher le nom et le prénom, nous allons simplement indiquer à l'interpréteur razor d'afficher le formateurDto.
Notre code d'affichage devient le suivant :
other |
.Columns(columns =>
{
columns.Command(commands => { commands.Edit().ButtonType(GridButtonType.Image); commands.Delete().ButtonType(GridButtonType.Image); }).Width(100).Title("Commands");
columns.Bound(o => o.Identifiant);
columns.Bound(o => o.Formation.Libelle).Width(200);
columns.Bound(o => o.Formateur).Width(400);
columns.Bound(o => o.Salle.Numero).Width(80);
columns.Bound(o => o.DebutSession).Format("{0:dd/MM/yyyy}").Width(120);
columns.Bound(o => o.FinSession).Format("{0:dd/MM/yyyy}").Width(120);
})
|
Voici le rendu de la liste :
VII-F-2. Templates client
La création d'un template coté client se base globalement sur le même principe. Afin d'obtenir le même affichage pour le formateur que dans l'exemple précédent, il est nécessaire de créer un attribut permettant d'afficher le formateur en tant que chaine de caractère. Cet attribut devra posséder un UIHint. Voici un exemple :
other |
[DisplayName("Formateur"), UIHint("ListeFormateur")]
public String LeFormateur { get; set; }
|
La recherche des données remplira ce champ.
Ensuite il faudra créer uniquement un template pour l'édition. Il diffèrera légèrement de celui vu précédemment :
other |
@(Html.Telerik().DropDownList()
.Name("LeFormateur")
.BindTo(new SelectList((IEnumerable)ViewData["Formateurs"], "Identifiant", "Nom"))
)
|
Avant-dernière étape, il faut modifier la vue pour prendre en compte le template :
other |
@model List<GestFormat.Models.SessionFormationDto>
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@(Html.Telerik().Grid(Model)
.Name("Grid")
.DataKeys(keys => { keys.Add(p => p.Identifiant); })
.ToolBar(commands => commands.Insert().ButtonType(GridButtonType.Image).ImageHtmlAttributes(new { style = "margin-left:0" }))
.Columns(columns =>
{
columns.Command(commands => { commands.Edit().ButtonType(GridButtonType.Image); commands.Delete().ButtonType(GridButtonType.Image); }).Width(100).Title("Commands");
columns.Bound(o => o.Identifiant);
columns.Bound(o => o.Formation.Libelle).Width(200);
columns.Bound(o => o.LeFormateur).Width(400);
columns.Bound(o => o.Salle.Numero).Width(80);
columns.Bound(o => o.DebutSession).Format("{0:dd/MM/yyyy}").Width(120);
columns.Bound(o => o.FinSession).Format("{0:dd/MM/yyyy}").Width(120);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("_Index", "GridTemplate")
.Insert("_Insert", "GridTemplate")
.Update("_Update", "GridTemplate")
.Delete("_Delete", "GridTemplate"); ;
}
)
.Editable(editing => editing.Mode(GridEditMode.InLine))
.Footer(true)
)
@section HeadContent
{
<script type="text/javascript">
function onEdit(e) {
$(e.form).find('#LeFormateur').data('tDropDownList').select(function (dataItem) {
return dataItem.Text == e.dataItem['LeFormateur'];
});
}
</script>
}
|
Nous avons ajouté ici une section HeadContent qui contient du javascript. Ce dernier indique que sur l'appel de la fonction onEdit, le libellé LeFormateur sera modifié par une liste déroulante, celle définit dans le template.
Néanmoins, il est nécessaire de déclarer dans le layout principal la prise en compte de cette section juste avant la balise <body>:
other |
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
@(Html.Telerik().StyleSheetRegistrar().DefaultGroup(group => group.Add("telerik.common.css").Add("telerik.windows7.css").Combined(true).Compress(true)))</head>
@RenderSection("HeadContent", required:false)
<body>
|
NB : Notez qu'il est possible d'obliger chaque page à avoir une section HeadContent en modifiant le required:false en required:true.
VII-F-3. Les fonctions de mise à jour
Nous avions vu dans le paragraphe CRUD, la mise à jour des données via les fonctions Insert, Update et Delete.
Dans le cas des templates, il est nécessaire de modifier ces fonctions. Nous avons ici une liste déroulante avec les formateurs qui nous enverra l'identifiant du formateur sélectionné. La signature de la fonction update devient donc :
other |
[GridAction]
public ActionResult _Update(Int32 id, Int32 maListe)
{
Models.SessionFormationDto dto = new Models.SessionFormationDto {
Identifiant = id
};
if (TryUpdateModel(dto))
{
Models.SessionFormationFactory.Update(dto, maListe);
}
ViewData["Formateurs"] = Models.FormateurFactory.SelectAllForDdl();
return View(new GridModel(Models.SessionFormationFactory.SelectAllClient()));
}
|
De même la fonction d'insertion prendra en paramètre la liste déroulante
other |
[GridAction]
public ActionResult _Insert(Int32 maListe)
{
...
}
|
NB : Le nom du paramètre est important. Il doit être identique (insensible à la casse) au nom donné à la liste déroulante dans le template.
VII-F-4. Aller plus loin
Il est ensuite possible bien entendu de faire la même chose sur les autres champs, ajouter des fonctions de vérification sur les champs ou créer des templates plus complexes.
Il est également possible de créer des templates dans le cas de modification en pop-up. La modification s'effectue de la même façon.
Attention néanmoins, il m'arrive régulièrement des problèmes d'affichage au niveau des grilles lorsque j'utilise les templates et les fonctions de pagination (colonne de template légèrement décalé.) Il faut alors jouer avec les largeurs de colonne, ce qui peut se révéler fastidieux.
VIII. Conclusion
Cet article présente les premières possibilités de l'utilisation des composants Telerik en MVC. Ces composants permettent de réaliser simplement des interfaces stylées et automatisent des taches quelques fois rébarbatives en termes d'implémentation.
Une seule chose m'a réellement ennuyé lors de mes tests avec ces composants : il est vraiment difficile de personnaliser son style. Les fichiers css sont complexes, long et pas toujours très parlant. L'affichage des images se fait via un seul fichier et des coordonnées ciblant une zone de ce fichier. Là encore difficile de personnaliser son interface sur le sujet.
Il est possible d'utiliser le constructeur de style de Telerik à cette adresse : http://stylebuilder.telerik.com/.
IX. Liens
Le blog de Scott Guthrie : http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx
Site telerik MVC
Forum Telerik MVC
Les sources présentées sur cette page sont libres de droits
et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation
constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ©
2011 Julien Brasselet. Aucune reproduction, même partielle, ne peut être
faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc.
sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à
trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.