Header menu on new Service portal
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-15-2017 11:09 AM
Ok I have seen many post on the header menu being cloned and followed the directions in threads such as Service Portal Header Menu Issue
Note: I am not used to working with angular and am strictly going off articles read. I may be missing something small.
What I am trying to accomplish:
- Change the cart button to redirect to a custom widget for the cart.
What I have done.
- Created new cart widget named ssp_shopping_cart by cloning current cart widget, copied and renamed Angular ng-template scripts from original widget to ssp_large_shopping_cart.html and ssp_small_shopping_cart.html
- Cloned header menu, Copied and renamed angular ng-templates to sspDropdownTreeTemplate and sspMenuTemplate
- Created angular provider directive named sspDropdownTree with the following code and then went into the angular templates and edited the bottom line at each to match the directive as suggested in the article linked above.
</a>
<ssp-dropdown-tree ng-if="mi.type == 'menu' && mi.items.length" items="mi.items" />
/*! RESOURCE: /scripts/app.$sp/directive.spDropdownTree.js */
/* angular.module('sn.$sp').directive('spDropdownCustom', */
function () {
return {
restrict: 'E',
scope: {items: '='},
replace: true,
template: '<ul class="dropdown-menu">' +
'<li ng-repeat="mi in items" style="min-width: 20em;" ng-class="{\'dropdown-submenu\': mi.type == \'menu\', \'dropdown-menu-line\':$index < items.length - 1}" ng-include="getURL()">' +
'</ul>',
link : function(scope, element, attrs, controller) {
scope.getURL = function() {
return 'sspDropdownTreeTemplate';
}
}
}
};
(function($) {
$("body").on( "click", "a.menu_trigger", function(e) {
var current = $(this).next();
var grandparent = $(this).parent().parent();
if ($(this).hasClass('left-caret') || $(this).hasClass('right-caret'))
$(this).toggleClass('right-caret left-caret');
grandparent.find('.left-caret').not(this).toggleClass('right-caret left-caret');
current.toggle();
$(".dropdown-menu").each(function(i, elem) {
var elemClosest = $(elem).closest('.dropdown');
var currentClosest = current.closest('.dropdown');
if (!elem.contains(current[0]) && elem != current[0] && (!currentClosest.length || !elemClosest.length || elemClosest[0] == currentClosest[0]))
$(elem).hide();
})
e.stopPropagation();
});
$("body").on( "click", "a:not(.menu_trigger)", function() {
var root=$(this).closest('.dropdown');
root.find('.left-caret').toggleClass('right-caret left-caret');
});
})(jQuery);
;
Problem:
- First problem I have had is the links we have for 'Service Catalog' 'Request' and 'Switch to Legacy' start to load but time out and I am unable to click on anything that point. the cart and my user name do show up.... but there is no functionality to them.
It's worth noting that if I just take the OOTB header menu, clone it and add the angular ng-templates to it without any further edits the same behavior is observed. At that point if I had the angular provider directive, the same thing occurs.
Any help is appreciated. I like the new Service Portal, this part is just throwing me for a loop.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-10-2017 08:43 AM
a
I did find the answer
I will look for what I did, I think I had missed something in the widget code that pointed to correct angular. I will copy and paste what code I have and you can see if it works for you.
There is one other thing you have to check I remember it being something about small and large but still looking for it. Ill update as soon as I remember
SSP Header Menu body HTML
<ul class="nav navbar-nav">
<div class="header-loader" ng-show="loadingIndicator">
<div class="hidden-xs sp-loading-indicator la-sm">
<div></div>
<div></div>
<div></div>
</div>
</div>
<li ng-repeat="item in data.menu.items" ng-class="{dropdown: item.items.length > 0}" ng-include="'spMenuTemplate'"></li>
<!-- Shopping cart stuff -->
<li ng-if="options.enable_cart && data.isLoggedIn" class="dropdown hidden-xs">
<a href="javascript:void(0)"
data-toggle="dropdown"
id="cart-dropdown"
uib-tooltip-template="'item-added-tooltip.html'"
tooltip-placement="bottom"
tooltip-trigger="'none'"
tooltip-is-open="$parent.itemAddedTooltipOpen"
title="${Cart}">
<i class="fa fa-shopping-cart" aria-hidden="true"></i>
<span ng-bind-html="'${Cart}'"></span>
<span ng-if="cartItemCount > 0" class="label label-as-badge label-primary sp-navbar-badge-count">{{cartItemCount}}</span>
</a>
<div class="dropdown-menu cart-dropdown">
<sp-widget widget="data.cartWidget"></sp-widget>
</div>
</li>
<li ng-if="options.enable_cart && data.isLoggedIn" class="dropdown visible-xs">
<a href="?id=ssp_sc_cart"
title="${Cart}">
<i class="fa fa-shopping-cart" aria-hidden="true"></i>
<span ng-bind-html="'${Cart}'"></span>
<span ng-if="cartItemCount > 0" class="label label-as-badge label-primary sp-navbar-badge-count">{{cartItemCount}}</span>
</a>
</li><script>
<div ng-click="toggleCart()" class="item-added-tooltip">${Item has been added to your cart.}</div>
</script>
</ul>
Server Script
(function(){
// build menus
var menu_id = $sp.getValue('sys_id'); // instance sys_id
var gr = new GlideRecord('sp_instance_menu');
gr.get(menu_id);
data.menu = {};
data.menu.name = gr.name.getDisplayValue();
data.menu.items = $sp.getMenuItems(menu_id);
data.isLoggedIn = GlideSession.get().isLoggedIn();
if (data.isLoggedIn)
data.cartWidget = $sp.getWidget("ssp-shopping-cart", {cartTemplate: "ssp_small_shopping_cart.html"});
})();
Client Controller
function (snRecordWatcher, $scope, spUtil, $rootScope, $timeout) {
$scope.loadingIndicator = $rootScope.loadingIndicator;
$scope.cartItemCount = 0;
$scope.itemAddedTooltipOpen = false;
$scope.$on("$sp.service_catalog.cart.count", function($evt, count) {
$scope.cartItemCount = count;
});
var cancelTooltipPromise;
$scope.$on("$sp.service_catalog.cart.add_item", function() {
$timeout.cancel(cancelTooltipPromise);
$scope.itemAddedTooltipOpen = true;
cancelTooltipPromise = $timeout(function() {
$scope.itemAddedTooltipOpen = false;
}, 3000);
});
$scope.$on('sp_loading_indicator', function(e, value) {
$scope.loadingIndicator = value;
});
$scope.toggleCart = function() {
$timeout.cancel(cancelTooltipPromise);
$scope.itemAddedTooltipOpen = false;
$timeout(function() {
$("#cart-dropdown").dropdown("toggle");
});
}
// Get list of record watchers
var record_watchers = [];
if ($scope.data.menu.items) {
for(var i in $scope.data.menu.items) {
var item = $scope.data.menu.items[i];
if (item.type == 'scripted') {
if (item.scriptedItems.record_watchers)
record_watchers = record_watchers.concat(item.scriptedItems.record_watchers);
}
if (item.type == 'filtered') {
record_watchers.push({'table':item.table,'filter':item.filter});
}
}
}
// Init record watchers
for (var y in record_watchers){
var watcher = record_watchers[y];
//console.info('Record Watcher: '+watcher.table+' : '+watcher.filter);
snRecordWatcher.initList(watcher.table, watcher.filter);
}
$scope.$on("record.updated", function(evt) {
spUtil.update($scope);
});
}
Angular Provider
/*! RESOURCE: /scripts/app.$sp/directive.spDropdownTree.js */
/* angular.module('sn.$sp').directive('spDropdownCustom', */
function () {
return {
restrict: 'E',
scope: {items: '='},
replace: true,
template: '<ul class="dropdown-menu">' +
'<li ng-repeat="mi in items" style="min-width: 20em;" ng-class="{\'dropdown-submenu\': mi.type == \'menu\', \'dropdown-menu-line\':$index < items.length - 1}" ng-include="getURL()">' +
'</ul>',
link : function(scope, element, attrs, controller) {
scope.getURL = function() {
return 'spDropdownTreeTemplate_custom';
}
}
}
};
(function($) {
$("body").on( "click", "a.menu_trigger", function(e) {
var current = $(this).next();
var grandparent = $(this).parent().parent();
if ($(this).hasClass('left-caret') || $(this).hasClass('right-caret'))
$(this).toggleClass('right-caret left-caret');
grandparent.find('.left-caret').not(this).toggleClass('right-caret left-caret');
current.toggle();
$(".dropdown-menu").each(function(i, elem) {
var elemClosest = $(elem).closest('.dropdown');
var currentClosest = current.closest('.dropdown');
if (!elem.contains(current[0]) && elem != current[0] && (!currentClosest.length || !elemClosest.length || elemClosest[0] == currentClosest[0]))
$(elem).hide();
})
e.stopPropagation();
});
$("body").on( "click", "a:not(.menu_trigger)", function() {
var root=$(this).closest('.dropdown');
root.find('.left-caret').toggleClass('right-caret left-caret');
});
})(jQuery);
;
spMenuTemplate
<a ng-if="item.items.length == 0 && !item.scriptedItems" ng-href="{{item.href}}" target="{{item.url_target}}">{{ item.label }}</a>
<a ng-if="item.items.length > 0" href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ item.label }} <span class="caret"></span></a>
<ul ng-if="item.items.length > 0" class="dropdown-menu" role="menu">
<li ng-repeat="item in item.items" ng-include="'spMenuTemplate'" />
</ul>
<a ng-if="item.scriptedItems.count > 0" href="javascript:void(0)" data-toggle="dropdown" title="{{item.hint}}">
<span ng-bind-html="item.label"></span>
<span ng-if="!item.scriptedItems.omitBadge" class="label label-as-badge label-primary sp-navbar-badge-count">{{item.scriptedItems.count}}</span>
</a>
<ssp-dropdown-tree ng-if="item.scriptedItems.count > 0" items="item.scriptedItems.items" />
spDropdownTreeTemplate_custom
<a ng-if="mi.type == 'link'" title="{{mi.title}}" target="{{mi.target}}" href="{{mi.href}}">
{{mi.title | characters:60}}
</a>
<a ng-if="mi.type == 'record' && !mi.__page" title="{{mi.short_description}}" href="?id=ticket&table={{mi.__table}}&sys_id={{mi.sys_id}}">
<span>{{mi.short_description | characters:60}}</span>
<span class="block color-primary text-muted">
<span class="block" style="float: right">
<sn-time-ago timestamp="mi.sys_updated_on" />
</span>
{{mi.number}}
</span>
</a>
<a ng-if="mi.type == 'record' && mi.__page" title="{{mi.short_description}}" href="?id={{mi.__page}}&table={{mi.__table}}&sys_id={{mi.sys_id}}">
<span>{{mi.short_description | characters:60}}</span>
<span class="block color-primary text-muted">
<span class="block" style="float: right">
<sn-time-ago timestamp="mi.sys_updated_on" />
</span>
{{mi.number}}
</span>
</a>
<a ng-if="mi.type == 'request'" title="{{mi.short_description}}" href="?id=sc_request&table={{mi.__table}}&sys_id={{mi.sys_id}}">
<span>{{mi.short_description | characters:60}}</span>
<span class="block color-primary text-muted">
<span class="block" style="float: right">
<sn-time-ago timestamp="mi.sys_updated_on" />
</span>
{{mi.number}}
</span>
</a>
<a ng-if="mi.type ='approval'" title="{{mi.short_description}}" href="?id=approval&table={{mi.__table}}&sys_id={{mi.sys_id}}">
<span ng-if="mi.short_description">{{mi.short_description | characters:60}}</span>
<span class="block color-primary text-muted">
<span class="block" style="float: right">
<sn-time-ago timestamp="mi.sys_updated_on" />
</span>
{{mi.number}}
</span>
</a>
<a ng-if="mi.type == 'menu' && mi.items.length" title="{{mi.title}}" href="javascript:void(0)" class="menu_trigger right-caret">
{{mi.title | characters:60}}
</a>
<ssp-dropdown-tree ng-if="mi.type == 'menu' && mi.items.length" items="mi.items" />=
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-10-2017 08:51 AM
at a glance, your code looks ok.
i have successfully cloned the header menu widget and customized it.
one other thing; In your "itscSpDropdownTreeTemplate" and "itscSpDropdownTree", please ensure that you are referencing the cloned version of your 'header menu' widget.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-10-2017 08:58 AM
Found it, Sorry for the wall of text
Under the Shopping Cart widget I had to copy it and edit a few things add the following angulars as well, ssp_large_shopping_cart.html and small_shopping_cart.html Shown below
SSP Shopping Cart
Body HTML
<div ng-if="options.cartTemplate">
<div ng-include="options.cartTemplate"></div>
<sp-widget widget="c.editVariablesModal" ng-if="c.editVariablesModal"></sp-widget>
<sp-widget widget="c.saveCartModal" ng-if="c.saveCartModal"></sp-widget>
</div>
<div ng-if="!options.cartTemplate">
<div class="alert alert-danger" role="alert">
<strong>${Error}: </strong>
${Please provide a cart template to render.}
</div>
</div>
Server script
(function() {
var m = data.msgs = {};
m.createdMsg = gs.getMessage("Created");
m.trackMsg = gs.getMessage("track using 'Requests' in the header or");
m.clickMsg = gs.getMessage("click here to view");
var userID = gs.getUser().getID();
var cart = new SPCart(input.cartName, userID);
if (input && input.action === "edit_item") {
data.editVariablesModal = $sp.getWidget('widget-modal', {embeddedWidgetId: 'sp-variable-editor', embeddedWidgetOptions: {sys_id: input.itemID, table: "sc_cart_item", isOrdering: true}});
return;
}
if (input && input.action === "update_quantity") {
var cartItemGR = new GlideRecord("sc_cart_item");
if (cartItemGR.get(input.itemID)) {
cartItemGR.setValue("quantity", input.quantity);
cartItemGR.update();
}
}
if (input && input.action === "checkout") {
cart.setSpecialInstructions(input.additionalDetails);
cart.setRequestedFor(input.cart.requested_for);
cart.setDeliveryAddress(input.deliverTo);
var request = cart.placeOrder();
data.requestData = {
number: request.getValue("number"),
table: request.getTableName(),
sys_id: request.getUniqueValue()
}
cart.setSpecialInstructions("");
cart.setRequestedFor(userID);
cart.setDeliveryAddress("");
}
if (input && input.action === "remove_item") {
var itemGR = new GlideRecord('sc_cart_item');
if (itemGR.get(input.removeItemID))
itemGR.deleteRecord();
}
if (input && input.action === "save_cart") {
var newCart = new SPCart(input.newCartName, userID);
newCart.loadCart(cart.getCartID());
}
data.sys_properties = {
twostep_checkout: gs.getProperty("glide.sc.checkout.twostep", "false") == 'true'
};
var cartID = cart.getCartID();
data.saveCartModal = $sp.getWidget('widget-modal', {embeddedWidgetId: 'sc_save_bundle', embeddedWidgetOptions: {}});
data.cart = cart.getCartObj();
data.cartItems = cart.getItems();
})();
Client Controller
function ($scope, spUtil, $location) {
var c = this;
c.m = $scope.data.msgs;
c.deliverTo = "";
c.additionalDetails = "";
$scope.$on("$sp.service_catalog.cart.update", function() {
$scope.server.update().then(function() {
$scope.$emit("$sp.service_catalog.cart.count", getItemCount());
});
});
c.updateQuantity = function(item) {
c.server.get({
action: "update_quantity",
itemID: item.sys_id,
quantity: item.quantity
}).then(function(response) {
$rootScope.$broadcast("$sp.service_catalog.cart.update");
});
}
c.triggerCheckout = function($evt, twostepCheckout) {
if (twostepCheckout) {
$location.url('?id=ssp_sc_cart');
return;
}
$evt.stopPropagation();
$evt.preventDefault();
c.checkoutInProgress = true;
c.data.action = "checkout";
c.data.deliverTo = c.deliverTo;
c.data.additionalDetails = c.additionalDetails;
c.server.update().then(function(response) {
c.data.action = null;
c.checkoutInProgress = false;
var requestData = $scope.data.requestData;
issueMessage(requestData.number, requestData.table, requestData.sys_id);
$rootScope.$broadcast("$sp.service_catalog.cart.update");
});
}
c.removeItem = function($evt, item) {
$evt.stopPropagation();
$evt.preventDefault();
$scope.server.get({
cartName: "DEFAULT",
action: "remove_item",
removeItemID: item.sys_id
}).then(function(response) {
c.data.cart = response.data.cart;
c.data.cartItems = response.data.cartItems
$rootScope.$broadcast("$sp.service_catalog.cart.update");
});
}
c.editItem = function(itemID) {
c.server.get({
itemID: itemID,
action: "edit_item"
}).then(function(response) {
var myModalCtrl;
var unregister = $scope.$on('$sp.service_catalog.cart.update', function(){
myModalCtrl.close();
});
var myModal = angular.copy(response.data.editVariablesModal);
myModal.options.afterOpen = function(ctrl){
myModalCtrl = ctrl;
};
myModal.options.afterClose = function() {
unregister();
c.editVariablesModal = null;
myModalCtrl = null;
};
c.editVariablesModal = myModal;
})
}
c.saveBundle = function() {
var saveCartModalCtrl;
var unregister = $scope.$on('$sp.service_catalog.cart.save_cart', function(){
saveCartModalCtrl.close();
});
var saveCartModal = angular.copy(c.data.saveCartModal);
saveCartModal.options.afterOpen = function(ctrl){
saveCartModalCtrl = ctrl;
};
saveCartModal.options.afterClose = function() {
unregister();
c.saveCartModal = null;
saveCartModalCtrl = null;
};
c.saveCartModal = saveCartModal;
}
c.requestedFor = {
displayValue: c.data.cart.requested_for_display_name,
value: c.data.cart.requested_for,
name: 'requested_for'
};
$scope.$on("field.change", function(evt, parms) {
if (parms.field.name == 'requested_for')
c.data.cart.requested_for = parms.newValue;
});
function issueMessage(n, table, sys_id) {
var page = table == 'sc_request' ? 'sc_request' : 'ticket';
var t = c.m.createdMsg + " " + n + " - ";
t += c.m.trackMsg;
t += ' <a href="?id=' + page + '&table=' + table + '&sys_id=' + sys_id + '">' + c.m.clickMsg + '</a>';
spUtil.addInfoMessage(t);
}
$scope.$emit("$sp.service_catalog.cart.count", getItemCount());
function getItemCount() {
return c.data.cartItems.length || 0;
}
}
ssp_large_shopping_cart.html
<div>
<div ng-show="c.data.cartItems.length > 0" class="panel panel-primary b">
<table id="cart" class="table table-hover table-condensed">
<thead>
<tr>
<th style="width: 52%;">${Product}</th>
<th style="width: 10%;">${Price}</th>
<th style="width: 8%;">${Quantity}</th>
<th style="width: 10%;">${Subtotal}</th>
<th style="width: 10%;"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in c.data.cartItems track by item.sys_id | orderBy: 'order'">
<td data-th="Product">
<div class="row">
<div class="col-sm-2 hidden-xs"><img ng-show="item.picture" ng-src="{{item.picture}}" alt="..." class="img-responsive item-image"/></div>
<div class="col-sm-10">
<h4 class="nomargin"><a ng-href="?id=sc_cat_item&sys_id={{item.item_id}}">{{item.name}}</a></h4>
<p class="hidden-xs">{{item.short_description}}</p>
</div>
</div>
</td>
<td>
<strong>{{item.display_price}}</strong>
<div ng-show="item.recurring_price > 0">+ {{item.display_recurring_price}} {{item.recurring_frequency_display}}</div>
</td>
<td data-th="Quantity">
<input type="number"
ng-if="item.show_quantity"
class="form-control text-center"
ng-model="item.quantity"
min="1"
max="99"
ng-model-options="{ updateOn: 'blur' }"
ng-change="c.updateQuantity(item)">
<span ng-if="!item.show_quantity">-</span>
</td>
<td>
<strong>{{item.subtotal_price}}</strong>
<div ng-show="item.recurring_subtotal > 0">+ {{item.recurring_subtotal_price}} {{item.recurring_frequency_display}}</div>
</td>
<td class="actions" data-th="">
<button class="btn btn-info btn-sm" ng-show="item.has_options" ng-click="c.editItem(item.sys_id)"><i class="fa fa-pencil"></i></button>
<button class="btn btn-danger btn-sm" ng-click="c.removeItem($event, item)"><i class="fa fa-trash-o"></i></button>
</td>
</tr>
</tbody>
</table>
<div class="panel-footer clearfix">
<div class="pull-right">
<h4 class="text-bold">${Total price}: {{c.data.cart.display_subtotal}}</h4>
<h5 class="text-bold" ng-repeat="(key, value) in c.data.cart.recurring_subtotals">+ {{value}} {{key}}</h5>
</div>
</div>
</div>
<div class="panel b" ng-show="c.data.cartItems.length > 0">
<div class="order-details-container form-group">
<div class="order-details requested-for-details">
<div>
<label>${Requested For}</label>
<sn-record-picker field="c.requestedFor" table="'sys_user'" display-field="'name'" value-field="'sys_id'" search-fields="'name'" page-size="100" ></sn-record-picker>
</div>
<div>
<label>${Deliver To}</label>
<textarea class="form-control" ng-model="c.deliverTo"></textarea>
</div>
</div>
<div class="order-details special-instructions-details">
<label>${Special Instructions}</label>
<textarea class="form-control" ng-model="c.additionalDetails"></textarea>
</div>
</div>
<div class="panel-footer">
<a href="?id=ssp_sc_home" name="submit" ng-click="triggerOnSubmit()" class="btn btn-default m-r-xs">${Continue Shopping}</a>
<button ng-disabled="c.checkoutInProgress" name="submit" ng-click="c.triggerCheckout($event)" class="btn btn-primary m-l-xs pull-right">
<span ng-show="!c.checkoutInProgress">${Checkout}</span>
<span ng-show="c.checkoutInProgress">${Ordering...}</span>
</button>
<a class="btn btn-default"
ng-click="c.saveBundle()">${Save as Bundle}</a>
</div>
</div>
<div ng-show="c.data.cartItems.length == 0" class="panel panel-default b">
<div class="panel-body">
<div class="empty-state-content">
<span class="fa fa-shopping-cart"></span>
<h3>${Your shopping cart is empty}</h3>
<p>${Once you have added items to your shopping cart, you can check out from here.}</p>
<a class="btn btn-primary" href="?id=ssp_sc_home">${View the Catalog}</a>
</div>
</div>
</div>
</div>
ssp_small_shopping_cart.html
<div class="panel">
<div class="panel-body" ng-if="c.data.cartItems.length > 0">
<ul class="media-list" ng-if="c.data.cartItems.length > 0">
<li class="media" ng-repeat="item in c.data.cartItems track by item.sys_id | orderBy: 'order'">
<div class="media-left">
<a ng-href="?id=sc_cat_item&sys_id={{item.item_id}}">
<img ng-show="item.picture" ng-src="{{item.picture}}" alt="..." class="img-responsive item-image"/>
</a>
</div>
<div class="media-body">
<a ng-href="?id=sc_cat_item&sys_id={{item.item_id}}"><label class="media-heading">{{item.name}}</label></a>
<p>{{item.short_description}}</p>
<p class="quantity-price">
<span class="quantity">{{item.quantity}} x</span><span class="price">{{item.display_price}}</span>
<span class="recurring" ng-show="item.recurring_subtotal > 0">+{{item.recurring_subtotal_price}} {{item.recurring_frequency_display}}</span>
</p>
<a href="javascript:void(0)" ng-click="c.editItem(item.sys_id)" ng-if="item.has_options">${Edit}</a>
</div>
<div class="media-right">
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-clear"
ng-click="c.removeItem($event, item)">
<i class="fa fa-times-circle" aria-hidden="true"></i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div class="panel-body" ng-show="c.data.cartItems.length == 0">
<div class="empty-state-content small-cart">
<span class="fa fa-shopping-cart small-cart"></span>
<h4>${Your shopping cart is empty}</h4>
<p>${Once you have added items to your shopping cart, you can check out from here.}</p>
</div>
</div>
<div ng-if="c.data.cartItems.length > 0" class="panel-footer align-right">
<label class="subtotal">${Total price}: <strong>{{c.data.cart.display_subtotal}}</strong></label>
<label ng-repeat="(key, value) in c.data.cart.recurring_subtotals" class="subtotal">+ {{value}} {{key}}</label>
</div>
<div class="panel-footer">
<div class="btn-group btn-group-justified" role="group">
<div class="btn-group" role="group">
<a type="button"
class="btn btn-default"
ng-href="?id=ssp_sc_cart">${View Cart}</a>
</div>
<div class="btn-group" role="group" ng-if="c.data.cartItems.length > 0">
<button ng-disabled="c.checkoutInProgress"
ng-click="c.triggerCheckout($event, c.data.sys_properties.twostep_checkout)"
class="btn btn-primary">
<span ng-show="!c.checkoutInProgress">${Checkout}</span>
<span ng-show="c.checkoutInProgress">${Ordering...}</span>
</button>
</div>
</div>
</div>
</div>

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-10-2017 09:45 AM
I have no idea what the issue was.
When I tried to copy your code and just change to my names of things, it was still not working.
So I gave up and used your naming conventions and copied *every*single*thing* exactly as it was (except for the link to your catalog page that wouldn't exist on my system) and now it loads fine.
I guess somewhere along the line I made a typo or something. But at least I have a working place to start from now.
Thanks so much for the help!
Shannon
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-10-2017 09:49 AM
I remember how frustrating that was, Glad I could help out a bit!