In NopCommerce I need to display the shopping cart outside of the the HeaderLinks partial, where should I add a new controller? - nopcommerce

I need to display the shopping cart outside of the the HeaderLinks partial which takes the cart items out of the model passed by the CommonController.HeaderLinks action. By creating a new controller with an action that passes the cart info I was able to get the custom ui element from our template working. Right now the controller is inside a custom plugin I got going for some other stuff. The way I see it I have two options:
Leave the controller in the plugin project and live with the fact that if the plugin for some reason is not installed (i.e. a fresh checkout from a new dev.) the theme is going to break, possibly redirecting the user to the error view.
Put the controller in the Controllers folder at Nop.Web with the downside that this would add an extra step to the process of upgrading NopCommerce. If similar issues arise this could get ugly pretty quick.
So my question is: where is the best place to put the controller? Or is there a simpler way to do this thing with the shopping cart?
Regards,
Jose

i will show you a shortcut way to solve it. First create a partial (razor) view e.g _CustomPartialView and then add these usings at the top inside the partial view
#using Nop.Core;
#using Nop.Core.Infrastructure;
#using Nop.Services.Orders;
then next is to query the shopping cart which is easy becuase nopCommerce has already static way of accessing depency resolver method i.e EngineContext.Current.Resolve<T>(). In your case (for shopping cart) it could be the following;
#{
var shoppingCartEnabled = EngineContext.Current.Resolve<Nop.Services.Security.IPermissionService>()
.Authorize(Nop.Services.Security.StandardPermissionProvider.EnableShoppingCart);
var customer = EngineContext.Current.Resolve<IWorkContext>().CurrentCustomer;
int shoppingCartItems = 0;
if (customer.HasShoppingCartItems)
{
shoppingCartItems = customer.ShoppingCartItems
.Where(sci => sci.ShoppingCartType == Nop.Core.Domain.Orders.ShoppingCartType.ShoppingCart)
.LimitPerStore(EngineContext.Current.Resolve<IStoreContext>().CurrentStore.Id)
.ToList()
.GetTotalProducts();
}
if (shoppingCartEnabled)
{
<div class="header-right pull-right wrap-cart hidden-xs ">
<div class="cart-top pull-right">
<div id="cart">
<span class="icon fa fa-shopping-cart"></span>
<div class="heading">
<a href="#Url.RouteUrl("ShoppingCart")" class="ico-cart dropdown-toggle visible-md visible-lg" data-toggle="dropdown" data-hover="dropdown">
<h4 class="cart-label">
#T("ShoppingCart")
<span>#T("ShoppingCart.HeaderQuantity", shoppingCartItems)</span>
</h4>
</a>
</div>
<div class="content">
#if (!String.IsNullOrWhiteSpace(Html.Action("FlyoutShoppingCart", "ShoppingCart").ToString()))
{
<li>#Html.Action("FlyoutShoppingCart", "ShoppingCart")</li>
}
</div>
</div>
</div>
</div>
}
}
Let me know if you need more help :)

Related

Controller action not being called on button click

I have an ASP .Net core MVC 2.0 app where I implemented a shopping cart for an e-commerce site as outlined in this video series. In the app, user can enter search queries for items which are displayed in a table. Each item in the table can be clicked on to display another page that has additional details for that item as well as a add to cart button.
The site features for searching, displaying the item results, and the details page are all implemented as actions in one controller class while the shopping cart functionality is all implemented in a separate controller class.
For some reason, when I click on the "Add to Cart" button for an item, a url of the form http://<hostname>/<controllerName>/<controllerACtion>/<id>is requested, but the corresponding controller action isn't called. This is strange because I'm using essentially the same code to call the action for adding to shopping cart as I did for displaying details. For this reason, I think the issue is related to the setup of the routes.
Here is the route setup in startup.cs:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=resortDeals}/{action=Index}/{id?}");
routes.MapRoute(
name: "shoppingcart",
template: "{controller=ShoppingCartController}/{action=AddToShopingCart}/{id?}");
});
Here is the shopping cart controller structure:
public class ShoppingCartController : Controller
{
public ViewResult Index()
{
...
}
public RedirectToActionResult AddToShopingCart(int dealId)
{
...
}
}
Below is the code for how the action is being called once the add to cart button is clicked:
<div class="addToCart text-right">
<p class="button ">
<a class="btn btn-success" id="cartButton" asp-controller="ShoppingCartController" asp-action="AddToShoppingCart" asp-route-id="#Model.RecNo">
Add to cart
</a>
</p>
</div>
What could be preventing the controller action from being called once the button is clicked?
I had an issue after publishing on the production server, when clicking on the button there was no response and I had to submit the button using Javascript.
<div class="addToCart text-right">
<p class="button ">
<button class="btn btn-success" onclick="search(#Model.RecNo)">
Add to cart
</button>
</p>
</div>
<script>
function addToCart(recNo) {
document.getElementById('cartForm').action = "/ShoppingCart/AddToShoppingCart/" + recNo;
document.getElementById('cartForm').submit();
}
</script>
I don't think you need the following route because the default route will handle the shoppingcart routes as well.
template: "{controller=ShoppingCartController}/{action=AddToShopingCart}/{id?}");
Also, try
<a class="btn btn-success" id="cartButton" asp-controller="ShoppingCart" asp-action="AddToShoppingCart" asp-route-id="#Model.RecNo">
I have removed the Controller word from asp-controller attribute
Also, change the input parameter name of AddToShopingCart method to id instead of dealId
public RedirectToActionResult AddToShopingCart(int id)
{
...
}

How to display subsites of a page within grid columns of the grid layout on GetGridHtml() using Umbraco

I come across a issue on umbraco, suggest me how I can bind the subsites of a page within a grid layout of what I set as DataType. kindly do reply how to do it.
note:
I don't want to use strongly-typed model to implement grid layout.
#CurrentPage.GetGridHtml(Umbraco.AssignedContentItem,"postTiles",
"bootstrap3")
#CurrentPage.GetGridHtml(#Umbraco.RenderMacro("ArticlesList"),"postTiles","bootstrap3")
//ArticlesList
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#{ var selection = CurrentPage.Children.Where("Visible").OrderBy("CreateDate desc"); }
<section class="container">
<div class="row">
#foreach (var item in selection)
{
<div class="col-md-3">
<img src="#Umbraco.Media(item.ArticleFeaturedImage).Url" style="width: 200px; height: 120px;" />
<h3>
#item.Name
</h3>
<p>
— posted under #item.ArticleCategory
· #String.Format("{0:dddd, MMMM d, yyyy}", #item.CreateDate)
· by #item.WriterName.ToString().ToLower()
</p>
<p>#Umbraco.Truncate(#item.ArticleDescription,100)</p>
</div>
}
</div>
</section>
If you want to have a custom rendering of some content in the Grid, you need to either:
Use a Macro and have content editors pick the Macro in the Grid
Create a custom property editor and specific the rendering partial in the package.manifest
Use a grid editor tool such as LeBlender or DocType Grid Editor to create a custom editor and assign a custom partial for rendering
I'm not sure exactly if that's what you're looking for, but I think these may get you on the right track.

How to customize Silverstripe login page content?

I'm using SilverStripe 3.5.3 I want to customize content ($Content) of the Security/login page. How do I do it?
You can also modify the page template by putting a template file named Security_login.ss in your templates/Layout directory.
The contents of one i've used in a previous project is:
<div class="row security-spacer">
<div class="large-12 columns">
<h1>$Title</h1>
<div class="typography">$Content</div>
<div class="row">
<div class="large-6 columns">
$Form
</div>
</div>
</div>
</div>
You can also create templates for
Security_changepassword.ss
Security_lostpassword.ss
Security_passwordsent.ss
You could extend the LoginForm class and create your own LoginForm anyway you like. You could base it off of the MemberLoginForm.php class.
Check out this article here which may help.
I know the OP asked specifically for its theme, but in case someone wants to know how to do it on the code side of things, you can use the request object to determine that, like this:
/mysite/code/Page.php
public function anyMethod() {
$value = 'default';
if (Controller::curr()->getRequest()->getURL() === 'Security/login') {
$value = 'something else';
}
return $value;
}
(On SilverStripe 4.1.0, anyway)

How to hide navigation portlet after logout?

How to hide a navigation portlet after logging out? What I exactly want is, if a logged-in admin visits a site, the navigation portlet should appear and be visible to him until he logs out from the plone site. But if a normal user visits the plone site, the portlet should not appear.
A nice feature of Plone is the option to assign portlets not only to locations, but also to contenttypes and groups. To solve your request, simply assign the portlet to the group 'Administrators'.
To do that, go to your Plonesite's controlpanel, click 'Users and Groups', click on green tab 'Groups', click on 'Administrators', click on the tab 'Group portlets', add a portlet.
To reproduce this programtically, use Genericsetup (export portlets.xml of the site and include the relevant parts in your product).
For completeness: Similiar for assigning portlets to a contenttype, you go to the controlpanel, click 'Types', choose the wanted type (f.e. 'Event') of the dropdownlist and click on 'Manage portlets assigned to this content type', assign portlet. Progragramtically reproducable via exporting 'Types' and including it to your products.
Thank you all, for all the response towards my question. Unfortunately the solution you all provided doesn't work for me. So I myself Did like this to hide a navigation portlet when logged out.
Step 1: In overrides.zcml
<plone:portlet
name="navigation_bar"
interface="plone.app.portlets.portlets.navigation.INavigationPortlet"
assignment="plone.app.portlets.portlets.navigation.Assignment"
renderer=".browser.navi_portlet.navigation_portlet"
addview="plone.app.portlets.portlets.navigation.AddForm"
editview="plone.app.portlets.portlets.navigation.EditForm"
/>
<plone:portletRenderer
portlet="plone.app.portlets.portlets.navigation.INavigationPortlet"
class=".browser.navi_portlet.navigation_portlet"
layer=".interfaces.IThemeSpecific"
/>
renderer=".browser.navi_portlet.navigation_portlet" here browser is my folder which contains a file called navi_portlet with a method navigation_portlet.
step 2: navi_portlet.py:
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.CMFPlone import PloneMessageFactory as _
from plone.app.portlets.portlets.navigation import Renderer
from plone.app.layout.viewlets.common import PersonalBarViewlet
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from plone.app.layout.globals.interfaces import IViewView
class navigation_portlet(Renderer,PersonalBarViewlet):
_template= ViewPageTemplateFile('templates/nav_portlet.pt')
def nav_up(self):
mytal = PersonalBarViewlet.update(self)
what i did in navi_portlet.py is i just inherited the PersonalBarViewlet from viewlets(eggs folder) and Renderer from portlets(eggs folder). To override the default behavior to hide it when logged out.
step 3: nav_portlet.pt
<dl class="actionMenu deactivated" id="portlet portletNavigationTree"
tal:define="user_actions python:view.nav_up();root view/navigation_root"
tal:condition="python:view.user_actions and not view.anonymous">
<tal:block condition="not: view/anonymous">
<dt class="portletHeader"
tal:attributes="class python:view.hasName() and 'portletHeader' or 'portletHeader hiddenStructure'">
<span class="portletTopLeft"></span>
<a href="#"
class="tile"
tal:attributes="href string:${view/heading_link_target}"
tal:content="view/title"
i18n:translate="">Navigation</a>
<span class="portletTopRight"></span>
</dt>
<dd class="portletItem lastItem">
<ul class="navTree navTreeLevel0">
<li tal:define="selectedClass view/root_item_class;
li_class python:selectedClass and ' navTreeCurrentNode' or '';
normalizeString nocall:context/plone_utils/normalizeString;
section_title root/Title;
section python:normalizeString(section_title);"
tal:condition="view/include_top"
tal:attributes="class string:navTreeItem navTreeTopNode${li_class} section-${section}">
<div tal:define="rootIsPortal view/root_is_portal;
root_icon view/root_icon;
root_type root/portal_type;
root_type_class python:'contenttype-' + normalizeString(root_type);
root_class python:rootIsPortal and 'contenttype-plone-site' or root_type_class;">
<a tal:attributes="href root/absolute_url;
title root/Description;
class python:' '.join([root_class, selectedClass]).strip();">
<img tal:replace="structure root_icon/html_tag" tal:condition="not:rootIsPortal" />
<span tal:omit-tag=""
tal:condition="rootIsPortal"
i18n:translate="tabs_home">Home</span>
<span tal:condition="not:rootIsPortal"
tal:replace="root/Title">Root item title</span>
</a>
</div>
</li>
<li tal:replace="structure view/createNavTree">
SUBTREE
</li>
</ul>
<span class="portletBottomLeft"></span>
<span class="portletBottomRight"></span>
</dd>
What i tried to do in nav_portlet.pt is to merge both portlets(Navigation Portlet using Render(class)) and viewlets(PersonalBarViewlet). so that i used the user_action method from the PersonalBarViewlet Class (i.etal:condition="python:view.user_actions and not view.anonymous">) to hide the Navigation Portlet when logged out.
Hope You all get my points and what i did.
Thanks

Get method passing all values on form mvc3

#using (Html.BeginRouteForm("ProductSearch", FormMethod.Get))
{
<div class="page-title">
<h1>Search</h1>
</div>
<div class="clear">
</div>
<div class="search-inut">
//here there is code for product box of each product satisfying search condition
}
All products are passed as querystring, any way to avoid it?
e.g
http:\localhost:54632\mysite\q=sugar&sugar 5kg=1&sugar free=1..............
all the products in search result are added in querystring
Thanx
Change
//here there is code for product box of each product satisfying search condition
}
to
}
//here there is code for product box of each product satisfying search condition
MVC isn't like Web Forms (where your entire page was in a form), you can safely put parts outside the form.

Resources