Liferay DXP Soy portlet系列(一) 創建SOY portlet

Liferay DXP的portlet支持soy模板。通過soy模板我們可以利用Google Closure來創建豐富的web應用。

接下來我將帶領你來領略soy portlet的風騷。

所需工具:
    Liferay IDE 3.1. -- Liferay官方工具,用來創建portlet項目和運行gradle任務。
    Atom Editor. -- 專業的UI開發編輯工具。你也可以使用你管用的工具。

所需相關知識:
    熟悉Liferay OSGi portlet module開發。如果你不熟悉的話,可以參考這個博客來學習如何創建mvc portlet。


第1步: 使用soy框架創建portlet

我們先利用mvc項目模板創建一個mvc portlet module。這裏我命名項目爲sample-soy
和mvc portlet不同的是,我們的soy portlet類繼承與com.liferay.portal.portlet.bridge.soy.SoyPortlet類, 它其實也是MVCPortlet的子類。
將父類改名爲SoyPoetlet
這裏需要在build.gradle中添加依賴。

compileOnly group: "com.liferay", name: "com.liferay.portal.portlet.bridge.soy", version: "3.0.0"

然後將類的註解改成這樣:

@Component(
    immediate = true,
    property = {
            "com.liferay.portlet.add-default-resource=true",
            "com.liferay.portlet.application-type=full-page-application",
            "com.liferay.portlet.application-type=widget",
            "com.liferay.portlet.css-class-wrapper=table-wrapper",
            "com.liferay.portlet.display-category=category.sample",
            "com.liferay.portlet.header-portlet-css=/SoySample.css",
            "com.liferay.portlet.layout-cacheable=true",
            "com.liferay.portlet.preferences-owned-by-group=true",
            "com.liferay.portlet.private-request-attributes=false",
            "com.liferay.portlet.private-session-attributes=false",
            "com.liferay.portlet.render-weight=50",
            "com.liferay.portlet.scopeable=true",
            "com.liferay.portlet.use-default-template=true",
            "javax.portlet.display-name=Soy Sample Portlet",
            "javax.portlet.expiration-cache=0",
            "javax.portlet.init-param.copy-request-parameters=true",
            "javax.portlet.init-param.template-path=/",
            "javax.portlet.init-param.view-template=SoySample",
            "javax.portlet.name=soy_sample_portlet",
            "javax.portlet.resource-bundle=content.Language",
            "javax.portlet.security-role-ref=guest,power-user,user",
            "javax.portlet.supports.mime-type=text/html"
    },
    service = Portlet.class
)

根據這個註解,我們需要SoySample.soy作爲默認的顯示頁面。我們也會使用SoySample.scss作爲portlet的樣式文件。

第2步:NodeJS配置文件

我們會使用NodeJS來編譯我們的UI元素,例如soy,metal和其他js,css文件。

在項目根目錄下創建package.json文件,內容如下:
{
    "dependencies": {         "metal-component": "^2.10.0",         "metal-soy": "^2.10.0"     },     "devDependencies": {         "liferay-module-config-generator": "^1.2.1",         "metal-cli": "^4.0.1"     },     "name": "soy-sample",     "version": "1.0.0" }


將這個version和bnd.bnd中的version對應是一個很好的習慣。


第3步: 配置OSGi

將下面的代碼添加到bnd.bnd中,這樣bnd就會將package.jso包含進最終的jar文件中了,並且OSGi bundle需要soy capability。

Include-Resource: package.json
Require-Capability: soy;filter:="(type=metal)"

第4步,使用render方法定義所需變量

添加/修改 portlet類中的render方法

 @Override
    public void render(
            RenderRequest renderRequest, RenderResponse renderResponse)
        throws IOException, PortletException {
        template.put("msg", "Good Job!");
        super.render(renderRequest, renderResponse);
    }

我們會在soy模板中引用這個參數,並且顯示值爲"Good Job!"。

第5步,創建SoySample模板

在 src/main/resources/META-INF/resources/resources路徑下創建文件SoySample.soy文件,內容如下:

{namespace SoySample}
/**
 * Show portlet message in the view.
 * @param id
 * @param msg
 */
{template .render}
     <div id="{$id}">
        <div class="form-group">
            <div class="input-group">
                <span class="input-group-addon" id="inputGroupAddon01">Message:</span>
                <input aria-describedby="inputGroupAddon01" class="form-control" value="{$msg}" type="text">
            </div>
        </div>
        <div class="form-group">
            <div class="input-group">
                <input aria-describedby="inputGroupAddon02" class="form-control" placeholder="Recipient's username, ex. neil.jin ;)" type="text">
                <span class="input-group-addon" id="inputGroupAddon02">@liferay.com</span>
            </div>
        </div>
        <div class="form-group">
            <div class="input-group">
                <span class="input-group-addon">$</span>
                <input aria-label="Amount" class="form-control" type="text">
                <span class="input-group-addon">.00</span>
            </div>
        </div>
        <div class="form-group">
            <button class="btn btn-default" type="button">Donate</button>
        </div>
     </div>
{/template}

Closure需要模板聲明使用類似java-doc註釋式的聲明。{templlate .render}聲明式必要的。並且,所有定義的參數必須要在模板中使用,這也防止了定義無用的變量。
而且{template .render} 前面不能有空格。
每次修改完soy文件,最好運行 build soy任務重新生成soy.js文件。
在我的模板中,我使用了lexicon來創建前端,這樣兼容性和用戶體驗可以達到最佳,並且節省代碼。
在相同文件夾中創建一個SoySample.scss文件,內容可以留空。

運行gradle任務buildSoy。

第6步,運行測試

現在可以編譯並且部署jar到Liferay服務器進行測試了。 如果沒什麼問題的話,就會顯示這樣的界面。



第一次編譯的時候,任務需要下載所需的node模塊,可能需要等一會,node_module文件夾大概100多M。
有時候在npmInstall的時候會卡死,可以停止運行任務,再重新編譯就好了。


第7步 javascript

接下來我會爲我的soy模板添加javascript。
在SoySample.soy相同的目錄下創建一個SoySample.es.js文件,內容如下:

import Component from 'metal-component/src/Component';
import core from 'metal/src/core';
import dom from 'metal-dom/src/dom';
import Soy from 'metal-soy/src/Soy';
import templates from './SoySample.soy';
class SoySample extends Component {
}
//Register component Soy.register(SoySample, templates);
export default SoySample;

這樣JS的框架就完成了。


第8步:添加javascript方法
接下來我們會創建一個donate方法,並且在瀏覽器控制檯顯示一條消息。
將下面的方法加入到SoySample類中:

/**
     * donate to neil
     *
     * @param  {MouseEvent} event
     */
    donate(event) {
        console.log("donate successful");
     }

第9步,使用方法

我們會在用戶點擊donate按鈕的時候觸發這個方法,所以在donate按鈕中添加data-onclick="donate"


<button class="btn btn-default" data-onclick="donate" type="button">Donate</button>

完成之後,就可以重新編譯部署項目了。
在瀏覽器中點擊按鈕的話,會在控制檯看到一條消息"donate successful"。



希望你會喜歡。
項目的源碼在github上可以看到,方便你下載測試。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章