はじめまして、テラスカイの范です。
SalesforceのB2B Commerce はデフォルトの標準設定のまますぐに使用することができますが、多くの場合、拡張が必要になります。
管理パッケージであるこのアプリケーションの動作を変更するには、カスタムコードを使用して拡張と上書きを行いますが、今回はB2BCommerceの標準ページネーションを拡張する方法を紹介します。
B2B Commerceの概要については、下記の記事をご参照ください。
SalesforceのB2B Commerce はデフォルトの標準設定のまますぐに使用することができますが、多くの場合、拡張が必要になります。
管理パッケージであるこのアプリケーションの動作を変更するには、カスタムコードを使用して拡張と上書きを行いますが、今回はB2BCommerceの標準ページネーションを拡張する方法を紹介します。
B2B Commerceの概要については、下記の記事をご参照ください。
B2B Commerceで企業にもB2C体験を!<B2B Commerceの概要をご紹介します>
2019年2月に日本版がリリースされたB2B Commerceを紹介します。
B2B Commerceで何ができる?<商品管理編>
B2B Commerceの商品管理方法について紹介します。
はじめに
B2B Commerceのテクノロジースタックを簡単に説明します。
B2BCommerceはユーザーインターフェイスを備えたJavaScriptに広く依存しています。基本的に、次のテクノロジースタックに基づいて構築されています。
- jQuery (base, UI, and validation)
- Backbone
- Bootstrap
- Handlebars
他のライブラリも使用されますが、これらの4つはアーキテクチャの中核を形成します。
ページネーションを実装する前に、以下の手順で商品一覧メニューを作成します。
1、サブスクライバーページを作成します。Visualforceページ名は「productList」とします。
2、サブスクライバーページにメニューリンクを追加します。
3、CC管理でメニューキャッシュを更新します。
これで商品一覧ページの準備ができたので、さっそくページネーションの実装に入ります。
1、サブスクライバーページを作成します。Visualforceページ名は「productList」とします。
2、サブスクライバーページにメニューリンクを追加します。
3、CC管理でメニューキャッシュを更新します。
これで商品一覧ページの準備ができたので、さっそくページネーションの実装に入ります。
実装
まずはページネーションのコンポネントを用意します。
ページネーションのビューとテンプレートはB2BCommerceの標準のものをそのままで利用します。
ページネーションのビューとテンプレートはB2BCommerceの標準のものをそのままで利用します。
<apex:component >
<apex:attribute name="eLName" type="String" description="DOM object name"/>
<script type="text/javascript">
jQuery(function($) {
CCRZ.views.paginationView = CCRZ.CloudCrazeView.extend({
templateDesktop: CCRZ.util.template('paginationTmpl'),
desktopEl: '{!eLName}',
events: {
'click .firstAction': 'firstPage',
'click .lastAction': 'lastPage',
'click .previousAction': 'previousPage',
'click .nextAction': 'nextPage',
'click .gotoPage': 'gotoPage',
'change .sizeAction': 'changePageSize',
'click .resortAction': 'resort'
},
init: function () {
this.listenTo(this.model, 'reset', this.render);
},
hostRendered: function (context, options) {
if (options) {
this.hostView = options.hostView;
}
this.render();
},
withinViewChange: false,
managedSubView: true,
preViewChanged: function () {
this.withinViewChanged = true;
},
preRender: function () {
this.$el.html('');
v = this;
v.model.state.slidingWindowSize = parseInt(CCRZ.getPageConfig('pgbl.WndSz', '3'));
v.model.state.currentSlidingWindow = Math.floor((v.model.state.currentPage - 1) / v.model.state.slidingWindowSize) + 1;
v.model.state.startPage = (v.model.state.currentSlidingWindow - 1) * v.model.state.slidingWindowSize + 1;
if ((v.model.state.currentSlidingWindow * v.model.state.slidingWindowSize) <= v.model.state.totalPages) {
v.model.state.endPage = (v.model.state.currentSlidingWindow) * v.model.state.slidingWindowSize;
} else {
v.model.state.endPage = v.model.state.totalPages;
}
v.model.state.hasPrevious = v.model.hasPreviousPage();
v.model.state.hasNext = v.model.hasNextPage();
v.model.state.startItem = (v.model.state.currentPage - 1) * v.model.state.pageSize + 1;
if ((v.model.state.currentPage * v.model.state.pageSize) <= v.model.state.totalRecords) {
v.model.state.endItem = (v.model.state.currentPage) * v.model.state.pageSize;
} else {
v.model.state.endItem = v.model.state.totalRecords;
}
var itemsPerPage = CCRZ.getPageConfig('pgbl.itmPerP', '10,25,50,75');
v.model.state.itemsPerPagePLValues = itemsPerPage.split(",");
for (var i = 0; i < v.model.state.itemsPerPagePLValues.length; i++) {
v.model.state.itemsPerPagePLValues[i] = parseInt(v.model.state.itemsPerPagePLValues[i], 10);
}
},
renderDesktop: function () {
v.setElement($(this.desktopEl));
v.$el.html(v.templateDesktop(v.model.state));
},
postRender: function () {
if (!this.withinViewChanged && this.hostView) {
var eventName = 'pagination:' + this.hostView + ':rendered';
CCRZ.pubSub.trigger(eventName, this);
CCRZ.console.log('trigger=' + eventName + ' context=' + this);
}
this.withinViewChanged = false;
},
firstPage: function () {
this.model.getFirstPage();
},
previousPage: function () {
this.model.getPreviousPage();
},
nextPage: function () {
this.model.getNextPage();
},
lastPage: function () {
this.model.getLastPage();
},
setSorting: function (sortKey, asc) {
this.model.setSorting(sortKey, asc);
this.model.fullCollection.sort();
},
gotoPage: function (event) {
var pageNum = $(event.target).data('id');
this.model.getPage(pageNum);
},
changePageSize: function (event) {
v = this;
var pSize = parseInt($(event.currentTarget).val());
v.model.setPageSize(pSize, {
first: true
});
},
resort: function (event) {
}
});
});
</script>
<script id="paginationTmpl" type="text/template">
<div class="panel panel-default cc_panel cc_paginator">
<div class="panel-body cc_body">
<div class="row">
<div class="col-xs-4">
<p class="cc_paginator_legend">
{{pageLabelMap 'PaginatorItems'}} {{startItem}} - {{endItem}} {{pageLabelMap 'PaginatorOf'}} {{totalRecords}} {{pageLabelMap 'PaginatorTotal'}}
</p>
</div>
<div class="col-xs-4">
<div class="text-center cc_current_page">
{{pageLabelMap 'PaginatorPage'}}
{{#if hasPrevious}}
<a href="#" class="firstAction cc_first_action">{{pageLabelMap 'PaginatorFirst'}}</a>
<a href="#" class="previousAction pageAction cc_page_action">{{pageLabelMap 'PaginatorPrevious'}}</a>
{{/if}}
{{#for startPage endPage 1}}
{{#ifEquals this ../currentPage}}
{{safeQuote this}}
{{else}}
<a href="#" class="gotoPage cc_goto_page" data-id="{{safeQuote this}}">{{safeQuote this}}</a>
{{/ifEquals}}
{{/for}}
{{#if hasNext}}
<a href="#" class="nextAction pageAction cc_page_action">{{pageLabelMap 'PaginatorNext'}}</a>
<a href="#" class="lastAction cc_last_action">{{pageLabelMap 'PaginatorLast'}}</a>
{{/if}}
</div>
</div>
<div class="col-xs-4">
<div class="form-inline cc_form-inline cc_paginator_form pull-right">
<label for="itemsPerPage" class="cc_items_per_page">
{{pageLabelMap 'PaginatorShow'}}
<select id="itemsPerPage" class="form-control input-sm sizeAction cc_size_action">
{{#each this.itemsPerPagePLValues}}
<option value="{{safeQuote this}}" {{#ifEquals ../pageSize this}} selected {{/ifEquals}}>{{safeQuote this}}</option>
{{/each}}
</select>
{{pageLabelMap 'PaginatorPerPage'}}
</label>
</div>
</div>
</div>
</div>
</div>
</script>
</apex:component>pagination.component
次に商品一覧のVisualforceページを実装します。
※1 ページネーションを利用する際に、CloudCrazePageableからの拡張が必要です。
※2 modeは「server」「client」「infinite」がありますが、今回は「client」を指定します。
※3 stateはすべてのページネーション状態を格納するコンテナオブジェクトです。「firstPage」と「pageSize」プロパティーはそれぞれ、1と10を設定します。
※4 リモートアクションでコントローラーの「searchProduct」メソッドを呼び出し、商品一覧レコードを取得します。
※1 ページネーションを利用する際に、CloudCrazePageableからの拡張が必要です。
※2 modeは「server」「client」「infinite」がありますが、今回は「client」を指定します。
※3 stateはすべてのページネーション状態を格納するコンテナオブジェクトです。「firstPage」と「pageSize」プロパティーはそれぞれ、1と10を設定します。
※4 リモートアクションでコントローラーの「searchProduct」メソッドを呼び出し、商品一覧レコードを取得します。
<apex:page docType="html-5.0" sidebar="false" showHeader="false" standardStylesheets="false" applyHtmlTag="false" controller="ProductListCtrl">
<c:pagination eLName=".paginator"/>
<div class="paginator"></div>
<div class="productList"></div>
<script type="text/javascript">
jQuery(function($) {
var productListCollection = CCRZ.CloudCrazePageable.extend({ //※1
mode: 'client', //※2
silent: false,
state: { //※3
firstPage: 1,
pageSize: 10
},
className: 'ProductListCtrl',
fetchAllNavData: function (state, formdata, callback) {
this.invokeCtx('searchProduct', function (res) { //※4
callback(res.data);
}, { buffer: false, nmsp: false });
}
});
var productlistView = CCRZ.CloudCrazeView.extend({
templateDesktop: CCRZ.util.template('productListTmpl'),
init: function () {
var v = this;
v.coll = new productListCollection();
var paginationView = new CCRZ.views.paginationView({
model: v.coll
});
this.listenTo(v.coll, 'reset', this.ready);
paginationView.listenTo(
v.coll,
'pagination:host:rendered',
paginationView.hostRendered
);
this.generateDisplay(v.coll, function () {
v.render();
});
},
generateDisplay: function (coll, callback) {
coll.fetch({
success: function () {
if (_.isFunction(callback)) {
callback();
}
}
});
},
ready: function (dataList, args) {
this.coll = dataList;
this.render();
},
render: function () {
var v = this;
v.setElement('.productList');
v.$el.html(v.templateDesktop(v.coll.toJSON()));
}
});
new productlistView();
});
</script>
<script id="productListTmpl" type="text/template">
<table class="table table-striped">
<tr>
<th>SKU</th>
<th>名前</th>
<th>開始日</th>
<th>終了日</th>
<th>商品種別</th>
<th>ステータス</th>
<th>商品インデックス状況</th>
</tr>
{{#each this}}
<tr>
<td>{{ccrz__SKU__c}}</td>
<td>{{Name}}</td>
<td>{{date ccrz__StartDate__c}}</td>
<td>{{date ccrz__EndDate__c}}</td>
<td>{{ccrz__ProductType__c}}</td>
<td>{{ccrz__ProductStatus__c}}</td>
<td>{{ccrz__ProductIndexStatus__c}}</td>
</tr>
{{/each}}
</table>
</script>
</apex:page>productList.page
結果
もしナビゲーションのスタイルを変更したいという場合には、Bootstrapのpaginationを参考にしていただければ、ナビゲーションのスタイルも変えられると思います。
おわりに
ライブラリを使わずに、標準ページネーションとテンプレートを利用することで、ページネーションを作りましたが、いかがでしょうか。みなさんのB2B Commerceカスタマイズ開発に、お役に立てれば幸いです。
最後まで読んでいただきましてありがとうござした。
最後まで読んでいただきましてありがとうござした。
18 件


ポスト

