Ostatnio trafił mi się mały projekt w SharePoint, chodziło w nim o kilka rzeczy ale jedną z nich była opcja dodania do widoku Tiles opisu danego elementu pod Tile.

Z opisu proste? :) ale jak to życie z SharePointem, to co w opisie wydaje się proste jest najbardziej zagmatwaną opcją implementacyjną :)

Tak więc po kilku godzinach analizy odkryłem, że mam jedną opcję! Napisania własnego webpartu! :) Aż się nie mogłem doczekać tych 10-15 minutowych deploymentów, tych godzin spędzonych na VS które co chwile się wywala przy pracy z SharePoint. W ogóle, moje życie było piękne przez kilka godzin :)

Na szczęście jakimś cudem, zainteresował mnie tag JsLink w definicji XsltListViewWebPart. Uwaga, opis JsLink zawiera buga, nie jest to link do pliku XSLT a linki do plików JavaScript oddzielone od siebie znakiem |. Zacząłem googlać co to takiego wraz z wartością jaką widziałem w definicji od Tiles View – SP.UI.TilesView.js.

Okazało się, że jest to tak zwany Client Side Rendering Template – czyli kod, który renderuje to co widzimy za pomocą JavaScript. To znaczy, na początku następuje transformacja danych za pomocą XSLT do HTML a następnie z wykorzystaniem JavaScript to tego co my widzimy – powszechnie znany jako JavaScript Display Template (taka jest nazwa content type).

Super, stwierdziłem więc, że podmienię SP.UI.TilesView.js na swój i problem zgłowy… po 2h czytania (wersji .debug.js pliku) i próby zrozumienia co to jest $0_1.$01_00 itp. zrezygnowałem :)

Zacząłem, więc doczytywać o JsLink – bardzo przydatna okazała się strona LearninSharePoint i artykuł SharePoint 2013 JsLink Tutorial. Okazuje się, że mogę się wpiąć w proces renderowania każdego elementu. Co było dość fajne. Jednak jeżeli się pod to podepniemy to tracimy wykonywanie renderowania danego elementu przez główny JavaScript Display Template (albo u mnie tak było).

Ale podczas sprawdzania odkryłem kolejny problem, tak zwany Minimal Download Strategy w SharePoint. Chodzi o to, że ten MDS jak już raz coś załaduje i wykona to stwierdza, że HEJ ja już to wykonałem i drugi raz tego nie wykonam. Ma to trochę ręce i nogi, ale stanowiło problem nie do przejścia.

Na szczęście z ratunkiem przyszedł artykuł Register CSR-override on MDS enabled SharePoint 2013 site który opisuje jak obejść problem za pomocą dostępnych metod JavaScriptowych. Super!

Teraz pozostała jedynie kwestia tego, że przeciążam renderowanie każdego elementu a tego nie chcę. Chcę tylko i wyłącznie wykonać to raz, albo wtedy kiedy base template zostanie wykonany.

Z pomocą przyszedł artykyuł All you ever wanted to know about Client-Side Rendering in SharePoint 2013 – Part 1 w którym odkryłem metodę OnPostRender – wywoływaną po tym jak już cały nasz webpart zostanie wyświetlony. Super!

Mając już taką wiedzę, za pomocą następującego kodu, który zakłada, że jQuery jest dostępny na stronie oraz, że w polach widoku Tiles znajduje się pole MyDescFiled:

// Let us take care of MDS enabled site
RegisterModuleInit("/_catalogs/masterpage/TileWithDesc.js", RegisterTileViewOverride); 
RegisterTileViewOverride();

function RegisterTileViewOverride() {

    if (typeof SPClientTemplates === 'undefined' || SPClientTemplates === null)
        return;

    // Setup the template override 
    var overrideCtx = {};
    overrideCtx.Templates = {};
    // SP.UI.AssetLibrary._constants.assetLibraryBaseViewID = 40;
    overrideCtx.BaseViewID = 40;

    // 851 for Asset Tile View Lib - SP.UI.AssetLibrary._constants.assetLibraryTemplateType = 851;
    overrideCtx.ListTemplateType = 851;

    overrideCtx.OnPostRender = PostRenderHandler;

    // Register for template override
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
}

function PostRenderHandler(ctx) {
    try {
       
        var $tiles = $('.ms-tileview-tile-root');
        // removing height constraint
        $tiles.css('height', 'auto');
        $tiles.css('display', 'inline-block');
        $tiles.css('vertical-align', 'top');
        
        $tiles.each( function(idx, val) {
            var item = ctx.ListData.Row[idx],
                $this = $(this),
                $div = $('<div class="marker-desc" style="text-align: left; width:150px;overflow:hidden;padding: 3px;position: relative;"></div>'),
                $tabularBox = $this.find('.ms-tileview-tile-tabularBox');

            // no more jumping! when hovering :)
            $tabularBox.css('overflow', 'hidden');
            $div.append(item.MyDescFiled);
            $this.append($div);
            // we do not want float any more
            $this.removeClass('ms-tileview-tile-root');
        });
    }
    catch (err) {
        console.error(err);
    }
}

I wgrania go zgodnie z instrukcjami na stronach – do master pages, jak nie ma content type JavaScript Display Template to trzeba zaznaczyć w ustawieniach listy by się pojawił:

tilesview-with-desc-settings

Byłem wstanie zamienić wygląd Tiles View z:

Widok Tiles View przed zmianą
Widok Tiles View przed zmianą

Na:

Widok Tiles View po zmianie
Widok Tiles View po zmianie

Oczywiście, doszła konfiguracja webpartu po dodaniu na stronę:

Ustawienia WebPartu
Ustawienia WebPartu

Gdzie JsLink to:

// kod zostal podzielony na wiersze, trzeba to zmienic na jeden wiersz

clienttemplates.js|
SP.UI.TileView.js|
SP.UI.AssetLibrary.js|
callout.js|
~sitecollection/_catalogs/masterpage/TilesWithDesc.js

Nie ma co mówić, prosto nie było, ale fajnie, że taka możliwość istnieje. Szkoda tylko że MS nie udokumentował tego jakoś wybitniej. Ale dzięki temu, że istnieje taka opcja, załatwiłem problem bardzo szybko jak już wiedziałem co gdzie i jak :)

A wam się zdarzyło wykorzystać JsLink? Wiedzieliście w ogóle o takiej funkcjonalności? Co o tym sądzicie?

2 KOMENTARZE

Comments are closed.