Has anyone solved or knows how to solve the following situation given the implementation of the header in Spartacus?
I would like to show in the header, a layout on the right of two level blocks, and on the left of a single level block.
Objective Header Layout
I can't think of how to do it since I can't see how to wrap certain slots, given the Spartacus implementation for the header.
Given the implementation of the header in Spartacus, inside the StorefrontComponent I cannot replace it using the ConfigModule.withConfig ({...}, as CmsConfig)
I understand and already tried that I can replace the header, implementing an Outlet (cxOutletRef = "header"), but this makes it impossible to edit it through SmartEdit, which is not acceptable to me.
Any suggestion? Or possible solution?
As a last option it occurs to me that I can create a component type from the back, and map it from Angular using "ConfigModule.withConfig ({...}, as CmsConfig)" implementing the "conflicting two-level" block from scratch or even the entire header.
Thank you !
////// CORRECTION 09/23/20 //////
Outlets do not prevent editing via SmartEdit. It's necessary to indicate the Slot to which the component corresponds, this is easy to implement using the PageSlotComponent.
✔ Example:
<ng-template cxOutletRef="cx-header">
<header
cxSkipLink="cx-header"
[cxFocus]="{ disableMouseFocus: true }"
[class.is-expanded]="isExpanded$ | async"
(keydown.escape)="collapseMenu()"
(click)="collapseMenuIfClickOutside($event)"
>
<cx-page-slot position="MiniCart"></cx-page-slot>
</header>
<cx-page-slot position="BottomHeaderSlot"> </cx-page-slot>
<cx-global-message></cx-global-message>
</ng-template>
In this way, SmartEdit does allow you to edit the MiniCart component, within its corresponding slot.
🚫 Wrong way:
<ng-template cxOutletRef="cx-header">
<header
cxSkipLink="cx-header"
[cxFocus]="{ disableMouseFocus: true }"
[class.is-expanded]="isExpanded$ | async"
(keydown.escape)="collapseMenu()"
(click)="collapseMenuIfClickOutside($event)"
>
<cx-mini-cart></cx-mini-cart>
</header>
<cx-page-slot position="BottomHeaderSlot"> </cx-page-slot>
<cx-global-message></cx-global-message>
</ng-template>
you can indeed solve this with a custom layout configuration and additional CSS, but it's not necessary. I give you a few options to consider:
Option 1: Change the generated DOM
You can either provide a custom layout config as #pwavg suggests, or even introducing a custom storefront component.
If you introduce a custom layout config, you're limited by the sections we use in the storefront component. If you insist on custom sections (ie. an element that wraps the searchbox, login, mincart and nav), you need to introduce a custom storefront component. The disadvantage here is that you'll deviating away from standard Spartacus component, which might result in missing features in the future.
Option 2: Pure CSS
A pure CSS solution is the easiest. You do not need to change any actual DOM, but apply some custom CSS rules to the standard DOM. Grid system is indeed designed for this. It's a bit complex to start with, but would do the job.
You can actually achieve this with flexbox as well, but you'd need to move the logo slot out of the flexbox flow.
Here's an actual quick and dirty code snippet to demonstrate changing by a few CSS rules only. It comes with a few assumptions/limitations, but for most cases it might be fine.
header {
cx-page-slot.SiteLogo {
// we absolute position the logo, so it flows outside the flexbox system. this requires
// an hard-coded top position, that might be fine, but I don't know the details.
position: absolute;
top: 60px;
}
cx-page-slot.SearchBox {
// align searchbox to the left, not sure if that's required, but looks better
margin: 14px auto 14px 150px;
}
cx-page-slot.NavigationBar {
margin-left: 150px;
overflow: hidden;
}
// manipulate a very high logo to demonstrate this works
cx-page-slot.SiteLogo img {
height: 100px;
}
}
Result (sorry for the logo ;) )
Option 3: cx-header Outlet
I would say you should be able to use outlets as well, as this will get you closer to option 1 (changing the actual DOM). I can't think of a reason why it would not work in SmartEdit - but happy to learn if it is the case. I'd recommend in this case to use the cx-header outletRef, so you would replace the entire header.
I am not super experienced with Spartacus so this might not be the correct way. Just trying to think with you on this.
I think you can just extend you layoutconfig and style the slots with CSSGrid. So for example you layout could be something like this:
layoutSlots: {
header: {
lg: {
slots: [
'SiteLinks',
'SiteLogin',
'HeaderLinks',
'SiteLogo',
'NavigationBar',
'SearchBox',
'MiniCart',
'NavigationBar2',
],
},
slots: ... (for mobile view)
},
},
And create a custom css grid for the positions of the slot.
If you want to have more markup control you could use cxOutletRef to replace the header with something like:
<ng-template cxOutletRef="cx-header">
<header>
<div class="header-top">
<cx-page-layout section="headerTop"></cx-page-layout>
</div>
<div class="header-bottom">
<cx-page-layout section="headerBottom"></cx-page-layout>
</div>
</header>
</ng-template>
And then divide the slots between headerTop and headerBottom in you config.
I have single p:message for which I want to set display: inline-block.
I've tried the following:
<p:message ... styleClass="inline-block" style="display:inline-block;/>
But when I see the sources, both style and class are NOT rendered on the div with messages.
Is there any way to specify the custom CSS attributes to the p:message directly?
I'm aware I can wrap it with div and steer the CSS of the children of that div, but I'd like to avoid superfluous wrapping, if possible.
PrimeFaces version: 3.5.
Have to disagree with Hatem Alimam
As the mykong article goes, you should add your stylesheet to override the Primefaces CSS.
!important in CSS stylesheet is seen as bad practice. Check these quick SO answers to see what the SO community thinks:
Is !important bad for performance?
What are the implications of using “!important” in CSS?
Is it bad to use !important in css property
The last one has an answer in defense of the !important but brings about the problem when several !important rules come into play (and if you start using it without reserve, you are bound to have it blow in your face and they start cascading one after the other.
The right way to do it is either to make your stylesheet have precedence over the PF sheet, to make your selectors get precedence over the ones in PF in the cascading.
Google for CSS selector Specificity for more on how to make sure your rule is picked by the browser over the PF ones (I am at work now and can't access blogs).
Onto your specific question:
The attributes do not work because they are not coded in the component. Check the PF user guide for your particular PF version (at the time of this writing, you have not stated your version). The <p:messages> component has a rather peculiar way of rendering.
for your particular case, add the following rule:
.ui-messages.ui-widget {
display: inline-block;
}
I have a pretty simple horizontal menu that has a solid background with colored links. How do I change the color of the link when I'm at the targeted page?
I tried this #nice-menu-1 li a:active
but that only affects the color for a moment when I click on it. I want the color on that item of the menu to stay changed while I am on that page.
thanks
Elements are "active in the definition of the :active pseudo class when that element is being clicked or tapped. So what you describe above is expected behavior.
You'll need to:
Set a class on the link that corresponds to the current page
Target that class with CSS
Luckily, Nice Menus and Drupal handle #1 for you by adding an .active class to the <a> tag and an .active-trail class to the parent <li> tag.
So you can target those in CSS like this:
#nice-menu-1 li.active-trail a,
#nice-menu-1 li a.active { color: #0f0;}
I would like to put a custom icon in a p:menuButton, is this possible?
Yest it is possible. All you need to do is to override primefaces css classes generated for the p:menuButton.
Approach:
In the rendered web page you can right click on the generated p:menuButton and -> inspect element. There you can inspect all of the related css classes.
You can try to experiment with them (which I would advice, if you have time) for better understanding of css selectors and so on ...
The .ui-menubutton .ui-state-default .ui-icon are the classes that you need.
So now when you know which css classes are related to the icon you can override them :
Add .ui-menubutton .ui-state-default .ui-icon rule to your stylesheet (I assume you have one and it is sucesfully imported and working. If not check here.)
yourStyles.css :
.ui-menubutton .ui-state-default .ui-icon {
background: orange; /** insert your background image **/
}
This will override icons of all p:menuButtons used in your project. If you want to reduce it to some particular p:menuButton then add its ID to the style definition.
#menubID.ui-menubutton .ui-state-default .ui-icon {
background: orange; /** insert your background image **/
}
I have activated the extended menu via the Screen Options and in my menu item I have specified a class based on the css code added to the screeen.css file.
For example in the "Home" menu item I have specified a class of "red", and in the css I have added the following code.
.red { color: #FF0000}
Unfortunately this is not transposing to the template and I am not sure what I am doing wrong.
Checking this with firebug I notice the class is being added, however the color change is not appearing.
<li id="menu-item-154" class="red menu-item menu-item-type-post_type menu-item-
object-page current-menu-item page_item page-item-148 current_page_item menu-
item-154"> Home
Can anyone offer some suggestions to make this work?
The color might be specified in one of the other classes as well.
You can try to remove that or you can try to force the color via the CSS important attribute.
Try:
.red { color: #FF0000 !important;}