Ostatnio napisałem kilka słów o tym jak wyświetlić dodatkowe pole na webpartcie z thumbnails view. W tym samym projekcie trzeba było rozwiązać problem z wyświetlaniem szczegółów wątku – na webpartcie odpowiedzialnym za dyskusje, jak użytkownik kliknie na temat dyskusji to domyślnie przekierowywany jest na stronę szczegółów wątku. Ogólnie rozwiązanie dobre jak lubimy cały czas klikać back w przeglądarce ;)

Ja miałem za zadanie zrobić to tak by jednak z tej strony na której jest webpart użykownik nie był przekierowywany dalej, ale by wyświetlić informację o szczegółach wątku najlepiej na tej samej stronie.

Po wielu godzinach i próbach, okazało się to niemożliwe z domyślnymi webpartami, a próbowałem wszystkiego :) Doprowadziłem już nawet do sytuacji, że prawie działało tak jak miało działąć:

  1. Użytkownik klika na nazwę wątku
  2. Po prawej/lewej/na dole/górze (w zależności gdzie drugi webpart jest umiejscowiony) pokazywały się szczegóły wątku

Do tego to wyglądało tak jak powinno wyglądać – 1-1 tak jak byśmy oglądali szczegóły wątku i listy wątków. Problem polegał na tym, że wątki działają na zasadzie katalogów i opierają się baaaaardzo mocno o query string. Na tyle mocno się opierają, że bez query stringa zawierającego ścieżkę do folderu i widoku, webpart szczegółów dyskusji nie będzie działał po stronie klienckiej. Po stronie serwerowej możemy to wszystko sobie zmocować jak chcemy. Więc mimo, że wszystko wyglądało jak należało i dodawanie kolejnych odpowiedzi do szczegółów wątku też działało, to za nic w świecie nie działało odświeżanie tego webparta. Odświeżanie nie działało, gdyż refresh był robiony (i dalej jest) na bazie aktualnego URLa przeglądarki, który gdzieś w bebechach całego JS API od SharePoint był ukrywany na tyle, że nie miałem możliwości go podmienić (albo mi się po prostu nie udało)./

Rozwiązaniem okazały się dwie opcje:

  • Ablo iframe z załądowaną stroną – dość proste rozwiązanie, dodajemy opcję IsDlg=1 do query string i mamy minimalny szablon i każdy link otwierany będzie otwierany w nowym oknie. Minusy rozwiązania to próba dostosowania widoku tak by pasował do całej strony (suwaki itp. itd.), drugi ribbon plus problem z przechwyceniem kiedy powinien webpart zostać ukryty, czy przy zmianie widoku na liście wątku? Czy przy filtrowaniu listy wątków itp.? nagle z prostego rozwiązania zrobiło się dość skomplikowane, nie działające coś :)
  • Albo modal window – to samo co iframe ale w oknie, odpowiadamy, zamykamy i kontynuujemy dalej

Z iframe po kilku godzinach zrezygnowałem, i znów za pomocą JSLink osiągnąłem otwieranie każdego wątku w osobnym oknie.

Poniżej kod, jakby kogoś to interesowało (sposób instalacji taki sam jak ostatnio):

RegisterModuleInit("/_catalogs/masterpage/Discussion.js", RegisterDiscussionOverride);

RegisterDiscussionOverride();

function RegisterDiscussionOverride() {

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

    // Setup the template override 
    var overrideCtx = {};
    overrideCtx.Templates = {};
    overrideCtx.BaseViewID = 3;

    overrideCtx.ListTemplateType = 108;

    // Register endHTML render handler
    overrideCtx.OnPostRender = PostRenderDiscussionHandler;

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

function PostRenderDiscussionHandler(ctx) {
    try {
       
        $('.ms-comm-postMainContainer.ms-comm-postSubjectColumn > a').click(function (evt) {

            evt.preventDefault();

            var $this = $(this),
            href = $this.attr('href');

            var dialog = SP.UI.ModalDialog.showModalDialog({
                title: 'Some Title Disussion Thread View',
                url: href,
                autoSize: true,
                width: 1024,
                height: 800
            });

            return false;

        });      
    }
    catch (err) {
        console.error(err);
    }
}

Trzeba jeszcze tylko zmodyfikować webpart widoku tematów dyskusji by zawierał w polu JSLink wartośći:

// linie pociete, nalezy polaczyc w jedna
SP.UI.Discussion.js|
Discussion.js

PS.: mały bonus, skąd wiem, że jak jest IsDlg to link otworzy się w nowym oknie? stąd, że webparty msowe generują onclick dla a z wartością:

GoToLinkOrDialogNewWindow(this);return false;

a o to kod metody GoToLinkOrDialogNewWindow:

function GoToLinkOrDialogNewWindow(elm) {
    if (elm.href == null)
        return;
    if (Boolean((ajaxNavigate.get_search()).match(RegExp("[?&]IsDlg=1"))))
        window.open(elm.href);
    else
        GoToLink(elm);
}