CodeZine(コードジン)

特集ページ一覧

Scala+LiftフレームワークのView/Template

Scala+Liftによる実践Webアプリケーション開発(2)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2009/11/16 14:00
目次

Snippetからの出力内容

 リスト1のSnippetタグは、内部にHTMLタグやXMLタグを含んでいるのが分かると思います。Snippet内部に含まれているタグは、scala.xml.NodeSeqオブジェクトとして、Snippetの関数に引数で渡されます。form="POST"と指定することで、Snippetが出力した内容がformタグで囲まれます。

 リスト1の*2*3は、Snippet実行時に、動的に置き換える部分です。net.liftweb.util.Helpersオブジェクトのbind関数で、指定した名前空間のタグの内容を動的に置き換えることができます。bind関数については、本項の後半で説明しますので、今の段階では、Snippetタグ内部にある、任意の名前空間のタグは動的に置き換えることができる部分であるという理解でかまいません。

レイアウトの分離

 テンプレートには、ヘッダーやフッターなどを分割してレイアウトを分離する機能があります。mavenで生成したプロジェクトでは、最初からプロジェクトディレクトリ以下の「src/main/webApp/template-hidden」ディレクトリに、default.htmlというファイル名で、デフォルトのヘッダーやフッターを含むXHTMLファイルが配置されています。

 リスト1の*4で、ビルトインSnippetである<lift:surround with="default" at="content"> タグを利用して、レイアウトを指定しています。with="default"はレイアウト名の指定です。指定するレイアウト名は、「src/main/webApp/template-hidden」ディレクトリにあるhtmlファイル名になります。レイアウト名として"default"を指定しているので、レイアウトに利用されるファイルはdefault.htmlです。at="content"はレイアウト内に内容を挿入する位置を指定しています。挿入する位置は、レイアウト用htmlファイル内に、<lift:bind name="挿入する位置の名前">タグで指定されている名前になります。

 リスト2は、デフォルトで生成されるdefault.htmlの内容の一部です。*1<lift:bind name="content" />の部分が、リスト1の<lift:surround>タグの内容に置き換えられます。

[リスト2]default.htmlの内容(抜粋)
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:lift="http://liftweb.net/">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <meta name="description" content="" />
    <meta name="keywords" content="" />

    <title>Lift Web Framework</title>
    <lift:CSS.blueprint />
    <lift:CSS.fancyType />
    <script id="jquery" src="/classpath/jquery.js" type="text/javascript"/>
    <script id="json" src="/classpath/json.js" type="text/javascript"/>

...省略

  </head>
  <body>
    <div class="container">

...省略

      <!-- SiteMapに登録されているMenuに従ってメニュー生成 -->
      <div class="column span-6 colborder sidebar">
        <hr class="space" />
        <!-- SiteMapに設定されている内容からメニュー用リンクを生成するSnippet -->
        <lift:Menu.builder />
        <div>
          <!-- エラーメッセージが設定されている場合に表示するビルトインSnippet -->
          <lift:snippet type="msgs"/>
          <hr class="space" />
        </div>
      </div>

      <div class="column span-17 last">
        <!-- この部分が置き換えられる -->
        <lift:bind name="content" />  *1
      </div>

 ...省略

    </div>
  </body>
</html>

ビルトインSnippet

 Liftに標準で組み込まれているビルトインSnippetは、代表的なものとして以下のSnippetが用意されています。

代表的なビルトインSnippet
Snippet 説明
lift:Surround このタグが含む内容を、with属性で指定されたレイアウトファイル内へ、at属性で指定した位置に挿入します。 <lift:surround with="template_name">children</lift:surround>
lift:bind-at lift:Surroundタグ内で利用します。lift:Surroundタグでat属性を指定しない場合、このタグの内容がname属性で指定した位置に挿入されます。lift:Surroundタグ内で、ヘッダー部分とコンテンツ本文の2か所をレイアウトに挿入したい場合などは、このタグでそれぞれ挿入したい内容を囲みます。 <lift:surround with="default" ><lift:bind-at name="header">ヘッダー内容</lift:bind-at> <lift:bind-at name="contents">コンテンツ本文 </lift:bind-at></lift:surround>
lift:bind lift:Surroundタグで指定されるレイアウトファイル内で使用し、内容を挿入する位置を設定します。 <lift:bind name="content" />
lift:Loc このタグのname属性を元に、Boot.scalaで設定されているSiteMapの名前からリンクを作成します。 <lift:Loc name="menu_name" />
lift:Embed 他のテンプレートを指定して取り込むことができます。 <lift:embed what="other_template" />
lift:Ignore このタグの内容は、Liftがテンプレートをレンダリングする際に無視されます。 <lift:ignore>この部分は無視</lift:ignore>
lift:Children このタグで囲んだ内容をグルーピングできます。ajaxでHTMLの一部を返す際などに、XMLとして複数のタグをまとめる際に利用されます。 <lift:children><div>This is the first DIV</div> <div>This is the other DIV</div></lift:children>

Snippet

 テンプレートのレンダリングの過程で、SnippetタグはSnippetクラスの関数を呼び出した結果に置き換えられます。

 Snippetは、Scalaのクラスとして、snippetパッケージ内に作成します。アプリケーションのパッケージ名が、「demo.greeting」の場合、Snippetクラスは「demo.greeting.snippet」パッケージに配置されている必要があります。Snippetとして作成するクラス名は、任意の名前を使用してかまいません。

 リスト3は、Snippetの例です。

[リスト3]Snippetの例
// snippetパッケージに作成する
package demo.greeting.snippet

// クラス名は任意
class SampleSnipet {
  // 関数名は任意。引数にscala.xml.NodeSeqを受け取り、
  // 戻り値としてscala.xml.NodeSeqを返す
  def hello( xhtml:NodeSeq ):NodeSeq = {

    // User.currentUserで現在ログインしているユーザーを取得。
    // パターンマッチを利用して、ログインしていない場合は"Guest"を設定している
    var name = User.currentUser match {
      case Full(user) => user.shortName
      case _ => "Guest"
    }

    // bind関数を利用して、引数のXHTML内で<greeting:...>で始まるタグの
    // 内容を置き換える
    bind( "greeting",  *1
      xhtml,
      "name"   -> SHtml.text( name, name=_ ),           // テキストフィールドを生成  *2
      "submit" -> SHtml.submit( "Say hello", greeting ) // submitボタンを生成  *3
    )
  }
}

 Snippet関数は、引数にscala.xml.NodeSeqオブジェクトを受け取るように定義されていなければなりません。引数として渡されるNodeSeqオブジェクトは、テンプレートの中で該当するSnippetタグの中に含まれているXMLになります。引数で渡されたXMLを加工することで、テンプレートの内容に依存しない出力を生成することが可能です。Snippet関数は、出力としてテンプレートに埋め込む内容も、引数と同じくscala.xml.NodeSeqオブジェクトを返す必要があります。

 Snippet内で使用されているbind関数は、Snippet関数の引数に渡されたXHTMLの中で、特定の名前のタグの内容を置き換える関数です。例では、テンプレートファイル内に、「<greeting:name/>」と記述されている部分をテキストフィールドに、「<greeting:submit/>」と記述されている部分はsubmitボタンへと置き換えて出力されます。このbind関数を利用することで、Snippetの中にはHTMLタグを含まずに、かつテンプレートの内容に応じた出力を生成することができ、デザインと表示ロジックを完全に分離することが可能となっています。

 SHtml.text関数やSHtml.submit関数は、HTMLタグを生成するヘルパー関数です。SHtmlオブジェクトには、リンクやチェックボックスなどの各種のHTMLタグを生成する関数が多数用意されています。どのような関数があるかについては、本稿の後半にて紹介します。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:Scala+Liftによる実践Webアプリケーション開発

著者プロフィール

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

  • WINGSプロジェクト 尾崎 智仁(オザキ トモヒト)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5