SharePoint 2013 : Créer une WebPart de recherche de contenu personnalisée – partie 2

Dans l’épisode précédent…

Nous avons vu comment se comportait la WebPart de recherche de contenu standard. Nous avons commencé à la personnaliser afin d’afficher des liens « Plus d’infos » ainsi que « Voir tout ». Malheureusement, les propriétés de WebPart ne se sont pas affichées dans le panneau d’édition…

SharePoint 2013 : Créer une WebPart de recherche de contenu personnalisée – partie 1

Voyons ce qui se passe

Et pour cela regardons du côté de la classe ContentBySearchWebPart et notamment sa méthode « GetToolPart() »

cswp_reflector

 

On remarque que cette méthode nous retourne toujours un nouveau tableau de ToolPart. Pour contourner ce problème, on va surcharger la méthode au sein de notre WebPart.

 /// <summary>
 /// Override GetToolParts to put our custom properties into the properties panel
 /// </summary>
 /// <returns></returns>
 public override ToolPart[] GetToolParts()
 {
       List<ToolPart> tp = new List<ToolPart>(base.GetToolParts());
       tp.Add(new CustomPropertyToolPart());
       return tp.ToArray();
 }

Redéployez votre solution, vous devriez désormais voir vos propriétés dans le panneau d’édition de la WebPart.

cswp_customprops

Utiliser les propriétés de WebPart

Désormais, nous voulons récupérer ces valeurs pour les afficher dans nos résultats. Nous devons enrichir la requête envoyée avec nos propriétés de WebPart pour que les display templates y aient accès

        /// <summary>
        /// Override OnLoad to make the custom properties accessible for the displaytemplates
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            if (this.AppManager != null)
            {
                if (this.AppManager.QueryGroups.ContainsKey(this.QueryGroupName) &&
                    this.AppManager.QueryGroups[this.QueryGroupName].DataProvider != null)
                {
                    this.AppManager.QueryGroups[this.QueryGroupName].DataProvider.BeforeSerializeToClient +=
                        new BeforeSerializeToClientEventHandler(EnhanceQuery);
                }
            }

            base.OnLoad(e);
        }

        private void EnhanceQuery(object sender, BeforeSerializeToClientEventArgs e)
        {
            DataProviderScriptWebPart dataProvider = sender as DataProviderScriptWebPart;
            dataProvider.Properties.Add("Demo_SeeMoreText", this.SeeMoreText);
            dataProvider.Properties.Add("Demo_SeeMoreUrl", this.SeeMoreUrl);
            dataProvider.Properties.Add("Demo_ReadMoreText", this.ReadMoreText);
            dataProvider.Properties.Add("Demo_ReadMoreUrl", this.ReadMoreUrl);
        }

Voyons maintenant comment accéder à ces propriétés dans nos display templates .

Nous allons partir des display templates « Control_List » et « Item_Picture3Lines ».

Accéder aux paramètres de site :

site_settings_btn

Dans la rubrique « Galeries du concepteur web », cliquer sur « Pages maîtres et mises en page ».

cswp_settings_disptemp

Accéder au dossier « Display Templates ».

cswp_folder_disptemp

 

Puis, « Content Web Parts ».

cswp_folder_contentwp

Télécharger une copie de « Control_List.html » et une copine « Item_Picture3Lines.html ».

cswp_disptemp_files

Les ajouter dans un module à votre solution après les avoir renommés:

cswp_disptemp_module

 

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
     <Module Name="DisplayTemplates" Url="_catalogs/masterpage/Display Templates/Content Web Parts" RootWebOnly="TRUE">
        <File Path="DisplayTemplates\Demo_Item_Picture3Lines.html"
          Url="Demo_Item_Picture3Lines.html"
          Type="GhostableInLibrary"
          ReplaceContent="True"
          Level="Draft" />

        <File Path="DisplayTemplates\Demo_Control_List.html"
          Url="Demo_Control_List.html"
          Type="GhostableInLibrary"
          ReplaceContent="True"
          Level="Draft" />
     </Module>
</Elements>

Avant de modifier ces display templates, il faut comprendre la manière dont ils seront affichés sur la page. Voici un schéma :

 

Voici ce à quoi ressemble le code HTML du display template « Demo_Control_List ».

 <div id="Control_List">
    <!--#_ ... _#-->
    <ul class="cbs-List">
       _#= ctx.RenderGroups(ctx) =#_
    </ul>
    <!--#_ if (ctx.ClientControl.get_shouldShowNoResultMessage()) { _#-->
    <div class="_#= noResultsClassName =#_">_#= $noResults =#_</div>
    <!--#_ } _#-->
    <p>
       <a href="_#= seeMoreUrl =#_">_#= seeMoreText =#_</a>
    </p>
 </div>

Et le code HTML du display template “Demo_Item_Picture3Lines”.

<div id="Item_Picture3Lines">
   <!--#_..._#-->
   <div class="cbs-picture3LinesContainer" id="_#= containerId =#_" data-displaytemplate="_#= $htmlEncode(dataDisplayTemplateTitle) =#_">
      <div class="cbs-picture3LinesImageContainer" id="_#= pictureContainerId =#_">
      <!--#_ if(!linkURL.isEmpty){ _#-->
          <a class="cbs-pictureImgLink" href="_#= linkURL =#_" title="_#= $htmlEncode(line1.defaultValueRenderer(line1)) =#_" id="_#= pictureLinkId =#_">
      <!--#_ } _#-->
             _#= pictureMarkup =#_
      <!--#_ if(!linkURL.isEmpty){ _#-->
          </a>
      <!--#_ } _#-->
      </div>
      <div class="cbs-picture3LinesDataContainer" id="_#= dataContainerId =#_">
          <a class="cbs-picture3LinesLine1Link" href="_#= linkURL =#_" title="_#= $htmlEncode(line1.defaultValueRenderer(line1)) =#_" id="_#= line1LinkId =#_">
              <h2 class="cbs-picture3LinesLine1 ms-accentText2 ms-noWrap" id="_#= line1Id =#_"> _#= line1 =#_</h2>
          </a>
          <!--#_ if(!line2.isEmpty){ _#-->
          <div class="cbs-picture3LinesLine2 ms-noWrap" title="_#= $htmlEncode(line2.defaultValueRenderer(line2)) =#_" id="_#= line2Id =#_"> _#= line2 =#_</div>
          <!--#_ } if(!line3.isEmpty) { _#-->
          <div class="cbs-pictureLine3 ms-textSmall ms-noWrap" id="_#= line3Id =#_" title="_#= $htmlEncode(line3.defaultValueRenderer(line3)) =#_">_#= line3 =#_</div>
          <!--#_ } _#-->
          <p>
             <a href="_#= readMoreUrl =#_">_#= readMoreText =#_</a>
          </p>
       </div>
    </div>
</div>

Pour accéder aux propriétés que nous avons précédemment ajouté à notre WebPart, il faut accéder au context courant rendu possible grâce à l’objet « ctx » et à sa propriété « DataProvider ».

Concernant le lien « Voir plus » nous aurions donc :

ctx.DataProvider.get_properties()[« Demo_SeeMoreUrl »];

ctx.DataProvider.get_properties()[« Demo_SeeMoreText »];

Il faut donc remplacer « <!–#_ … _#– !> » par


        <!--#_

        if (!$isNull(ctx.ClientControl) &&

            !$isNull(ctx.ClientControl.shouldRenderControl) &&

            !ctx.ClientControl.shouldRenderControl())

        {

            return "";

        }

        ctx.ListDataJSONGroupsKey = "ResultTables";

        var $noResults = Srch.ContentBySearch.getControlTemplateEncodedNoResultsMessage(ctx.ClientControl);

 

        var noResultsClassName = "ms-srch-result-noResults";

 

        var ListRenderRenderWrapper = function(itemRenderResult, inCtx, tpl)

        {

            var iStr = [];

            iStr.push('<li>');

            iStr.push(itemRenderResult);

            iStr.push('</li>');

            return iStr.join('');

        }

        ctx['ItemRenderWrapper'] = ListRenderRenderWrapper;

 

        var siteURL = SP.PageContextInfo.get_siteServerRelativeUrl();

 

        var seeMoreUrl = siteURL + ctx.DataProvider.get_properties()["Demo_SeeMoreUrl"];

        var seeMoreText = ctx.DataProvider.get_properties()["Demo_SeeMoreText"];

        _#-->

Et pour le lien “Plus d’infos” nous aurions

ctx.DataProvider.get_properties()[« Demo_ReadMoreUrl »];

ctx.DataProvider.get_properties()[« Demo_ReadMoreText »];

Il faut donc remplacer « <!–#_ … _#– !> » par


        <!--#_

 

        var encodedId = $htmlEncode(ctx.ClientControl.get_nextUniqueId() + "_picture3Lines_");

 

        var linkURL = $getItemValue(ctx, "Link URL");

        linkURL.overrideValueRenderer($urlHtmlEncode);

 

        var line1 = $getItemValue(ctx, "Line 1");

        var line2 = $getItemValue(ctx, "Line 2");

        var line3 = $getItemValue(ctx, "Line 3");

 

        var pictureURL = $getItemValue(ctx, "Picture URL");

        var pictureId = encodedId + "picture";

        var pictureMarkup = Srch.ContentBySearch.getPictureMarkup(pictureURL, 100, 100, ctx.CurrentItem, "cbs-picture3LinesImg", line1, pictureId);

 

        line1.overrideValueRenderer($contentLineText);

        line2.overrideValueRenderer($contentLineText);

        line3.overrideValueRenderer($contentLineText);

 

        var containerId = encodedId + "container";

        var pictureLinkId = encodedId + "pictureLink";

        var pictureContainerId = encodedId + "pictureContainer";

        var dataContainerId = encodedId + "dataContainer";

        var line1LinkId = encodedId + "line1Link";

        var line1Id = encodedId + "line1";

        var line2Id = encodedId + "line2";

        var line3Id = encodedId + "line3";

            

        var dataDisplayTemplateTitle = "ItemPicture3Lines";

 

        var siteURL = SP.PageContextInfo.get_siteServerRelativeUrl();

        var listItemId = ctx.CurrentItem.ListItemID;

 

        var readMoreUrl = siteURL + ctx.DataProvider.get_properties()["Demo_ReadMoreUrl"] + "?itemID=" + listItemId;

        var readMoreText = ctx.DataProvider.get_properties()["Demo_ReadMoreText"];

         _#-->

Avant de terminer notre article, il faut publier les display templates sur votre site afin de générer le fichier Javascript associé, les télécharger et les ajouter à votre Module :


<?xml version="1.0" encoding="utf-8"?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <Module Name="DisplayTemplates" Url="_catalogs/masterpage/Display Templates/Content Web Parts" RootWebOnly="TRUE">

    

    <File Path="DisplayTemplates\Demo_Item_Picture3Lines.html" 

          Url="Demo_Item_Picture3Lines.html"  

          Type="GhostableInLibrary" 

          ReplaceContent="True" 

          Level="Draft" />

    

    <File Path="DisplayTemplates\Demo_Control_List.html" 

          Url="Demo_Control_List.html"  

          Type="GhostableInLibrary" 

          ReplaceContent="True" 

          Level="Draft" />

 

    <File Path="DisplayTemplates\Demo_Item_Picture3Lines.js" 

          Url="Demo_Item_Picture3Lines.js"  

          Type="GhostableInLibrary" 

          Level="Draft" 

          ReplaceContent="true">

      <Property Name="ContentType" Value="Display Template Code" />

    </File>

 

    <File Path="DisplayTemplates\Demo_Control_List.js" 

          Url="Demo_Control_List.js" 

          Type="GhostableInLibrary" 

          Level="Draft" 

          ReplaceContent="true">

      <Property Name="ContentType" Value="Display Template Code" />

    </File>

   

  </Module>

</Elements>

Ajouter vos propriétés à votre fichier WebPart :


?xml version="1.0" encoding="utf-8"?>

<webParts>

  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">

    <metaData>

      <type name="SharePointDemo.CustomContentSearchWebPart.CustomContentSearchWebPart, $SharePoint.Project.AssemblyFullName$" />

      <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>

    </metaData>

    <data>

      <properties>

        <property name="Title" type="string">SharePointDemo - CustomContentSearchWebPart</property>

        <property name="Description" type="string">My Web Part</property>

        <property name="SeeMoreUrl" type="string">#</property>

        <property name="SeeMoreText" type="string">See more</property>

        <property name="ReadMoreUrl" type="string">#</property>

        <property name="ReadMoreText" type="string">Read more</property>

      </properties>

    </data>

  </webPart>

</webParts>

 

Ajouter vos propriétés à votre fichier WebPart (CustomContentSearchWebPart.webpart)


?xml version="1.0" encoding="utf-8"?>

<webParts>

  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">

    <metaData>

      <type name="SharePointDemo.CustomContentSearchWebPart.CustomContentSearchWebPart, $SharePoint.Project.AssemblyFullName$" />

      <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>

    </metaData>

    <data>

      <properties>

        <property name="Title" type="string">SharePointDemo - CustomContentSearchWebPart</property>

        <property name="Description" type="string">My Web Part</property>

        <property name="SeeMoreUrl" type="string">#</property>

        <property name="SeeMoreText" type="string">See more</property>

        <property name="ReadMoreUrl" type="string">#</property>

        <property name="ReadMoreText" type="string">Read more</property>

      </properties>

    </data>

  </webPart>

</webParts>

Voilà, il ne vous reste plus qu’à déployer votre solution et votre WebPart de recherche de contenu personnalisée est terminée.

cswp_editmode_result

Téléchargez le projet sur github.

N’hésitez pas poster vos questions en commentaires.

Un commentaire. Laisser un commentaire

ANDRIAMAMPIONONA
septembre 20, 2016 10:49

[MissingWebPart] WebPart class [28c23aec-2537-68b3-43b6-845b13cea19f] is referenced [3] times in the database [SharePoint_AdminContent_], but is not installed on the current farm. Please install any feature/solution which contains this web part. One or more web parts are referenced in the database [SharePoint_AdminContent_], but are not installed on the current farm. Please install any feature or solution which contains these web parts.

Voila mon problème. Je n’arrive pas a le résoudre j’ai déjà tester le lancement d’une nouvelle requete sur Sql management Studio.
use [SharePoint_AdminContent_(guid)]

select DirName, LeafName
from dbo.AllDocs
where id in
(select tp_PageUrlID
from dbo.AllWebParts
where lower(tp_WebPartTypeId) = ’28c23aec-2537-68b3-43b6-845b13cea19f’)
Mais ce code ne donne rien

Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *