ServiceNow Japan Communityの質問
ウィジェットSC Category Pagesの編集方法について教えてください。
について、回答を作成したものの、なぜかRepryボタンが消えているため、コミュニティにて回答ができない。もし、Koheiさんがこの記事を見ていればいいのだが...という供養的な記事。
(というか、ServiceNow MVPの方の回答が見当違いでわら...)
元記事(QA)転載
Service Portal DesignerからウィジェットSC Category PagesのGrid Vewにした場合に表示される
Item/Description/PriceのフィールドのうちPriceの削除したいのですが方法がわかりません。
初心者なのでご存じの方いましたらお知恵をお貸しください。
現象の再現手順
まずは問題のスクリーンショットにたどり着くための導線...
1.platformのナビゲーションでService Portal > Service Portal HomeでPortalを開く
2.Portal右上のCatalogを押下する
3.検索バー下のBrowse by Categoriesを押下する
4.CategoryのHardwareを押下する
5.ListileをCard View -> List Viewに変更する
6.CatalogのListViewでHardwareのItem/description/priceが表示される(QA時点再現)
現象の解決(priceを消したい)
1.使用Widgetを特定し、表示する
パーツをCtrl + 右クリックで表示リストの「Widget in Editor」を押下する
2.使用Widget(今回はSC Category Page)のソースが表示される。なので、これをクローンしてからソースを改変する。(Clone "SC Category Page"をクリック)
2.2 名前をつける。私はClone SC Category Pageと命名。適当につけてOK
2.3 左上のプルダウンでクローンしたWidgetを選択(Clone SC Category Page)して表示変更する。
3.クローンのHTMLを変更する
下記にHTMLのソースを表示
<div class="m-t-sm " ng-class="{'hidden-xs' : hideItemWidget, 'm-l-sm': !isMobile}">
<h4 ng-if="data.error">{{data.error}}</h4>
<div ng-init="spSearch.targetCatalog()">
<div class="row">
<div class="col-xs-9">
<a ng-click="showCategories()" class="visible-xs m-b-sm pointer" aria-label="${All Categories}" role="button" tabindex="0" id="all-categories-link">
<i class="fa fa-chevron-left m-r-xs"></i> ${All Categories}
</a>
<h2 class="h4 m-t-none break-word">{{data.category.title}}</h2>
<p class="hidden-xs break-word">
{{data.category.description}}
</p>
</div>
<div class="col-xs-3" ng-if="!isMobile">
<div role="tablist" class="pull-right padder-t-sm text-lg toggle" ng-show="!data.error && data.items.length > 0">
<i id="tab-card"
role="tab"
class="fa fa-th tab-card-padding" ng-click="changeView('card')"
ng-keydown="switchTab($event)" aria-label="${Card View}"
ng-class="{'active' : view == 'card'}"
title="${Card View}"
data-toggle="{{!isTouchDevice() ? 'tooltip' : undefined}}"
data-placement="top"
data-container="body"
aria-selected="{{view == 'card'}}"
aria-label="${Card View}"
ng-attr-aria-controls="{{view == 'card' ? 'tabpanel-card-' + (data.category_id ? data.category_id : '') : undefined}}"
tabindex="{{view == 'card' ? '0' : '-1'}}"></i>
<span class="m-l-sm m-r-sm " aria-hidden="true"> | </span>
<i id="tab-grid"
role="tab"
class="fa fa-list-ul tab-card-padding"
ng-click="changeView('grid')"
ng-keydown="switchTab($event)"
ng-class="{'active' : view == 'grid'}"
title="${Table View}"
data-toggle="{{!isTouchDevice() ? 'tooltip' : undefined}}"
data-placement="top"
data-container="body"
aria-selected="{{view == 'grid'}}"
aria-label="${Table View}"
ng-attr-aria-controls="{{view == 'grid' ? 'tabpanel-grid-' + (data.category_id ? data.category_id : '') : undefined}}"
tabindex="{{view == 'grid' ? '0' : '-1'}}"></i>
</div>
</div>
</div>
<div class="row">
<div class="text-a-c" ng-if="showTopLoader">
<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
<span class="sr-only">${Loading...}</span>
</div>
<div class="col-sm-6 col-md-4" ng-if="!showTopLoader && !data.items.length && !data.error">
${No items in category}
</div>
<div id="tabpanel-grid-{{::data.category_id}}" role="tabpanel" aria-labelledby="{{'tab-grid'}}" ng-if="view == 'grid' && data.items.length > 0">
<table class="table table-striped item-table" aria-label="{{::data.category.title}}" aria-describedby="id-caption-category">
<caption id="id-caption-category"><span class="sr-only">{{::data.category.title}}</span></caption>
<thead>
<tr>
<th id="id-header-item" scope="col">${Item}</th>
<th id="id-header-description" scope="col">${Description}</th>
<th id="id-header-price" scope="col" ng-if="data.showPrices">${Price}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in data.items | orderBy: 'order' | limitTo: data.limit track by item.sys_id" ng-init="startItemList()">
<th id="id-item-{{item.sys_id}}" headers="id-header-item" scope="row" class="th-row-data">
<a sn-focus="{{::item.highlight}}" href="javascript:void(0);" ng-click="onClick($event, item)">
<div>
<img ng-src="{{::item.picture}}?t=small" ng-if="item.picture" alt="" class="m-r-sm m-b-sm item-image pull-left"/>
<span class="catalog-text-wrap">{{::item.name}}</span>
<span ng-if="item.content_type == 'external'"><span class="sr-only">${External Link}</span> ➚</span>
</div>
</a>
</th>
<td headers="id-header-description id-item-{{item.sys_id}}" class="catalog-text-wrap">{{::item.short_description}}</td>
<td headers="id-header-price id-item-{{item.sys_id}}" ng-if="data.showPrices">{{::item.price}}</td>
</tr>
</tbody>
</table>
</div>
<div id="tabpanel-card-{{::data.category_id}}" ng-if="view == 'card' && data.items.length > 0" role="tabpanel" aria-labelledby="{{'tab-card'}}">
<ul class="item-list-style-type-none item-card-row" role="list" aria-label="{{data.category.title}} ${items}">
<li class="item-card-column" ng-repeat="item in data.items | orderBy: 'order' | limitTo: data.limit track by item.sys_id" ng-init="startItemList()" role="listitem">
<div class="panel-{{::options.color}} item-card b">
<a href="javascript:void(0);" ng-click="onClick($event, item)" class="panel-body block height-100" sn-focus="{{::item.highlight}}" aria-labelledby="sc_cat_item_{{::item.sys_id}}" aria-describedby="sc_cat_item_short_desc_{{::item.sys_id}}">
<div>
<h3 class="h4 m-t-none m-b-xs text-overflow-ellipsis" title="{{::item.name}}" style="padding-bottom:1px" id="sc_cat_item_{{::item.sys_id}}">{{::item.name}}<span ng-if="item.content_type == 'external'"><span class="sr-only">${External Link}</span> ➚</span></h3>
<img ng-src="{{::item.picture}}?t=small" ng-if="item.picture" alt="" class="m-r-sm m-b-sm item-image pull-left" aria-hidden="true"/>
<div class="text-muted item-short-desc catalog-text-wrap" id="sc_cat_item_short_desc_{{::item.sys_id}}">{{::item.short_description}}</div>
</div>
</a>
</div>
<div class="panel-footer b">
<a aria-label="${View Details} {{::item.name}}" href="javascript:void(0);" ng-click="onClick($event, item)" class="pull-left text-muted">${View Details}</a>
<span ng-if="data.showPrices && item.hasPrice" class="pull-right item-price font-bold">{{::item.price}}</span>
</div>
</li>
</ul>
</div>
</div>
<div class="text-a-c" ng-if="!stopLoader && data.items.length > 0 && !data.error">
<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
<span class="sr-only">${Loading...}</span>
</div>
<div ng-if="data.show_more && !show_popular_item">
<div class="text-a-c">
{{data.more_msg}}
</div>
<button class="m-t-xs btn btn-default btn-loadmore" ng-click="loadMore()">
${Show More Items}
</button>
</div>
</div>
</div>
<now-message key="Catalogs" value="${Catalogs}"/>
上記ソースのうち、priceのListHeaderとListContentの生成部分が三箇所あるので、そこをコメントアウトする
<div class="m-t-sm " ng-class="{'hidden-xs' : hideItemWidget, 'm-l-sm': !isMobile}">
<h4 ng-if="data.error">{{data.error}}</h4>
<div ng-init="spSearch.targetCatalog()">
<div class="row">
<div class="col-xs-9">
<a ng-click="showCategories()" class="visible-xs m-b-sm pointer" aria-label="${All Categories}" role="button" tabindex="0" id="all-categories-link">
<i class="fa fa-chevron-left m-r-xs"></i> ${All Categories}
</a>
<h2 class="h4 m-t-none break-word">{{data.category.title}}</h2>
<p class="hidden-xs break-word">
{{data.category.description}}
</p>
</div>
<div class="col-xs-3" ng-if="!isMobile">
<div role="tablist" class="pull-right padder-t-sm text-lg toggle" ng-show="!data.error && data.items.length > 0">
<i id="tab-card"
role="tab"
class="fa fa-th tab-card-padding" ng-click="changeView('card')"
ng-keydown="switchTab($event)" aria-label="${Card View}"
ng-class="{'active' : view == 'card'}"
title="${Card View}"
data-toggle="{{!isTouchDevice() ? 'tooltip' : undefined}}"
data-placement="top"
data-container="body"
aria-selected="{{view == 'card'}}"
aria-label="${Card View}"
ng-attr-aria-controls="{{view == 'card' ? 'tabpanel-card-' + (data.category_id ? data.category_id : '') : undefined}}"
tabindex="{{view == 'card' ? '0' : '-1'}}"></i>
<span class="m-l-sm m-r-sm " aria-hidden="true"> | </span>
<i id="tab-grid"
role="tab"
class="fa fa-list-ul tab-card-padding"
ng-click="changeView('grid')"
ng-keydown="switchTab($event)"
ng-class="{'active' : view == 'grid'}"
title="${Table View}"
data-toggle="{{!isTouchDevice() ? 'tooltip' : undefined}}"
data-placement="top"
data-container="body"
aria-selected="{{view == 'grid'}}"
aria-label="${Table View}"
ng-attr-aria-controls="{{view == 'grid' ? 'tabpanel-grid-' + (data.category_id ? data.category_id : '') : undefined}}"
tabindex="{{view == 'grid' ? '0' : '-1'}}"></i>
</div>
</div>
</div>
<div class="row">
<div class="text-a-c" ng-if="showTopLoader">
<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
<span class="sr-only">${Loading...}</span>
</div>
<div class="col-sm-6 col-md-4" ng-if="!showTopLoader && !data.items.length && !data.error">
${No items in category}
</div>
<div id="tabpanel-grid-{{::data.category_id}}" role="tabpanel" aria-labelledby="{{'tab-grid'}}" ng-if="view == 'grid' && data.items.length > 0">
<table class="table table-striped item-table" aria-label="{{::data.category.title}}" aria-describedby="id-caption-category">
<caption id="id-caption-category"><span class="sr-only">{{::data.category.title}}</span></caption>
<thead>
<tr>
<th id="id-header-item" scope="col">${Item}</th>
<th id="id-header-description" scope="col">${Description}</th>
<!--<th id="id-header-price" scope="col" ng-if="data.showPrices">${Price}</th> -->
</tr>
</thead>
<tbody>
<tr ng-repeat="item in data.items | orderBy: 'order' | limitTo: data.limit track by item.sys_id" ng-init="startItemList()">
<th id="id-item-{{item.sys_id}}" headers="id-header-item" scope="row" class="th-row-data">
<a sn-focus="{{::item.highlight}}" href="javascript:void(0);" ng-click="onClick($event, item)">
<div>
<img ng-src="{{::item.picture}}?t=small" ng-if="item.picture" alt="" class="m-r-sm m-b-sm item-image pull-left"/>
<span class="catalog-text-wrap">{{::item.name}}</span>
<span ng-if="item.content_type == 'external'"><span class="sr-only">${External Link}</span> ➚</span>
</div>
</a>
</th>
<td headers="id-header-description id-item-{{item.sys_id}}" class="catalog-text-wrap">{{::item.short_description}}</td>
<!--<td headers="id-header-price id-item-{{item.sys_id}}" ng-if="data.showPrices">{{::item.price}}</td> -->
</tr>
</tbody>
</table>
</div>
<div id="tabpanel-card-{{::data.category_id}}" ng-if="view == 'card' && data.items.length > 0" role="tabpanel" aria-labelledby="{{'tab-card'}}">
<ul class="item-list-style-type-none item-card-row" role="list" aria-label="{{data.category.title}} ${items}">
<li class="item-card-column" ng-repeat="item in data.items | orderBy: 'order' | limitTo: data.limit track by item.sys_id" ng-init="startItemList()" role="listitem">
<div class="panel-{{::options.color}} item-card b">
<a href="javascript:void(0);" ng-click="onClick($event, item)" class="panel-body block height-100" sn-focus="{{::item.highlight}}" aria-labelledby="sc_cat_item_{{::item.sys_id}}" aria-describedby="sc_cat_item_short_desc_{{::item.sys_id}}">
<div>
<h3 class="h4 m-t-none m-b-xs text-overflow-ellipsis" title="{{::item.name}}" style="padding-bottom:1px" id="sc_cat_item_{{::item.sys_id}}">{{::item.name}}<span ng-if="item.content_type == 'external'"><span class="sr-only">${External Link}</span> ➚</span></h3>
<img ng-src="{{::item.picture}}?t=small" ng-if="item.picture" alt="" class="m-r-sm m-b-sm item-image pull-left" aria-hidden="true"/>
<div class="text-muted item-short-desc catalog-text-wrap" id="sc_cat_item_short_desc_{{::item.sys_id}}">{{::item.short_description}}</div>
</div>
</a>
</div>
<!--
<div class="panel-footer b">
<a aria-label="${View Details} {{::item.name}}" href="javascript:void(0);" ng-click="onClick($event, item)" class="pull-left text-muted">${View Details}</a>
<span ng-if="data.showPrices && item.hasPrice" class="pull-right item-price font-bold">{{::item.price}}</span>
</div>
-->
</li>
</ul>
</div>
</div>
<div class="text-a-c" ng-if="!stopLoader && data.items.length > 0 && !data.error">
<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
<span class="sr-only">${Loading...}</span>
</div>
<div ng-if="data.show_more && !show_popular_item">
<div class="text-a-c">
{{data.more_msg}}
</div>
<button class="m-t-xs btn btn-default btn-loadmore" ng-click="loadMore()">
${Show More Items}
</button>
</div>
</div>
</div>
<now-message key="Catalogs" value="${Catalogs}"/>
変更後は忘れずSaveする
4.変更Widgetを現状Widgetと差し替える
Portalを Ctrl+右クリックでPage in Designerを押下する
4.2 Widgetをfilterして見つける
4.3 Widgetをドラッグ&ドロップで挿入する
4.4 前のSC Category Pageをゴミ箱で削除する
priceが削除されている!
Appendix Descriptionカラムを右側において2Grid表示にしたい
上記のHTMLの部分をいくつかいじれば修正可能なはずです。未検証ですが、表示部分はWidgetのHTMLです。
上記、参考になれば幸いです。