čtvrtek 18. prosince 2014

ASP.NET MVC - sdílený helper

Tento článek by se možná hodil do série "Poznámky z code review" - ale vlastně je to jen další variace na téme DRY :-). Narazil jsem na to, že v jednom web projektu (ASP.NET MVC) se poměrně často generoval tooltip (v daném projektu ikonka, která při najetí myší ukáže boxík s dalšími údaji). Na každém místě, kde se i zobrazoval, byl použit téměř stejný kód, lišil se jen vlastním tělem tooltipu - tedy tím, jaké informace zobrazoval. Například na jednom místě vypadal kód na cshtml stránce takto:

<img width="14" height="14" onmouseout="$('#tooltip1').hide();" onmouseover="$('#tooltip1').css('display','inline');" style="margin-bottom:3px; inline-block;" alt="" title="" src="~/info.png">
<div id="tooltip1" style="display:none; position:relative;">
    <span class="arrow"></span>
    <div>
        <ul>
            <li><strong>@Model.Name</strong>@Model.Surname</li>
            <li><strong>@Model.Position</strong> - @Descriptions.Position</li>
        </ul>
        <p><i>@Descriptions.GeneralNote</i></p>
    </div>
</div>


Lepším přístupem v takovém případě se mi jeví založení sdílené helper metody - do adresáře App_Code se přidá soubor s názvem SharedHelpers.cshtml (název není až tak důležitý, ale jméno - tedy SharedHelpers - bude používáno pro volání helperu, tak je dobré s ohledem na tento fakt zvolit příhodné jméno. 

Souborů si můžete navíc založit více. Helper metoda, kterou v souboru definujeme, bude tak dostupná ze všech view (cshtml) v projektu a bude využívat templated razor delegate - více informací lze nalézt například na stránce http://haacked.com/archive/2011/02/27/templated-razor-delegates.aspx/ . Vlastní kód metody bude vypadat takto:

@helper Tooltip(params Func<dynamic, HelperResult>[] templates)
{
    <span class="hoverBox">
        <img src="~/icon.png" height="14" width="14" title="" alt="" />
        <div class="hoverTooltip">
            <span class="arrowShape"></span>
            <div>
                @foreach (var template in templates)
                {
                    @template(null)
                }
            </div>
        </div>
    </span>
}

Na ostatních - běžných - csthml stránkách bude použita jednoduše - stačí ji předat jenom razor kód těla konkrétního tooltipu a metoda jej "obalí" zbytkem kódu:

@SharedHelpers.Tooltip(
   @<span>
       <ul>
         <li><strong>@Model.Name</strong> – @Model.Surname</li>
         <li><strong>@Model.Position</strong> - @Descriptions.Position</li>
       </ul>
       <p><i>@Descriptions.GeneralNote</i></p>
  </span>)

Předávaný razor kód musí mít html značky uzavřené, tj. první a poslední značka musí být z jednoho páru. Protože to někdy nechceme (viz <span> v příkladě), zvolil jsem params definici pro sdílenou helper metodu a je jí tedy možné předat více samostatných razor kódů (tohle vše zní asi trochu kostrbatě, ale nevím jak to správně popsat česky):

@SharedHelpers.Tooltip(
   @<ul>
      <li><strong>@Model.Name</strong> – @Model.Surname</li>
      <li><strong>@Model.Position</strong> - @Descriptions.Position</li>
     </ul>,
   @<p><i>@Descriptions.GeneralNote</i></p>>)


Pokud vždy budete předávat jen jeden kus razor kódu, tak params pole vstupních parametrů sdílené helper metody není potřeba a můžete jej odstranit:

@helper Tooltip(Func<dynamic, HelperResult> template)
{
    <span class="hoverBox">
        <img src="~/icon.png" height="14" width="14" title="" alt="" />
        <div class="hoverTooltip">
            <span class="arrowShape"></span>
            <div>
               @template(null)
            </div>
        </div>
    </span>
}

 A málem bych zapomněl na css nahrazující javascript, to vypadá nějak takto:
...
       .hoverBox div.hoverTooltip {
             display: none;
             ...
       }

       .hoverBox:hover div.hoverTooltip {
             display: block;
       }
...

Programátor se pak nemusí při psaní razor kód zabývat správným kódem pro ikonku, vloží jen to, co chce mít zobrazené a o zbytek se postará sdílený helper.

Žádné komentáře:

Okomentovat