Add DIV Element to Layout of the Header - spartacus-storefront

Having a problem, that I need to add a Element to the NavigationBar in the Header for styling purposes
I would need to have
<header>
<cx-pagelayout>
<div>
<cx-pageslot>
The only option I see is to overwrite the storefront component but i would like to not overwrite a main component. Is there any other option that I not see?

I can see two ways of going about it.
Like you mentioned you could create your own storefront component and create a header with the DOM you want there.
You can use the outlets mechanism to replace the header with your custom component. This would look something like this:
<ng-template cxOutletRef="cx-header">
<custom-header></custom-header>
</ng-template>
or use the provideOutlet provider in your custom header's module like so:
providers: [
provideOutlet({
id: 'cx-header',
position: OutletPosition.REPLACE,
component: CustomHeaderComponent,
}),
],
In the above example, custom-header (CustomHeaderComponent) is your header component. Also note, you need to import the OutletRefModule in your module.
Note, if you use the HTML method: to override the header outlet, you need to put your OutletRef in the app.component.html

Related

How do I customize the a generated-index page in Docusaurus?

I have a generated-index page and I can see how to customize the on page title and description in the category.json for the directory, but is there a way to customize the items that are generated by the files that are in the same directory? for example:
tutorials
_category_.json
01-first-tutorial.md
02-second-tutorial.md
I want to be able to have an icon for each of the files and different text than what is pulled from those files first paragraph like seems to be the default. What I want perhaps looks something like this page, but the icons and text need to be links to the tutorial pages.
I have tried using a DocCardList, adding in descriptions, adding in items (failed), and changing each of my tutorial files, but so far no love.
EDIT:
They've come up with a new component called DocCardList which you can use in version 2.3.0.
Create an index.mdx file in your category folder.
Add the following:
import DocCardList from '#theme/DocCardList';
<DocCardList />
Swizzle or otherwise override this component in your src/theme folder to add custom styling, etc.
ORIGINAL ANSWER:
Maybe you could try swapping the generated index component using the docCategoryGeneratedIndexComponent prop (link to reference). That would replace all auto-generated index pages which might be what you want.
In docusaurus.config.js, in the presets section, add
presets: [
[
"classic",
/** #type {import('#docusaurus/preset-classic').Options} */
({
docs: {
sidebarPath: require.resolve("./sidebars.js"),
docCategoryGeneratedIndexComponent:
"#site/src/components/CategoryIndexPage",
},
// etc.
}),
],
],
And then try adding the following custom component under src/components/CategoryIndexPage.tsx:
import React from "react";
export default function CategoryIndexPage(props) {
return (
<pre>
<code>{JSON.stringify(props, null, 2)}</code>
</pre>
);
}
This will just show you what the prop structure is in the component.
When I looked in the theme component which generates this page, it uses
const category = useCurrentSidebarCategory();
But when I try that to get the list of items, I get the following error:
Hook useDocsSidebar is called outside the .
Maybe you can figure out the next steps, I was not able to. 😅
Alternatively, you can create an index.mdx file in your category folder and import a custom React component into that. That gives me the same context violation error, though.
# My custom category page
Some Markdown content here.
import CategoryIndex from "#site/src/components/CategoryIndex.tsx";
<CategoryIndex />

How get one single component (carousel) from element-ui if is imported as global config object?

Hi in project i have included element-ui.
In app.js:
import Element from 'element-ui'
and after:
Vue.use(Element, {locale})
So in my single file components template i can use carousel like this: (In this component is not any initialization carousel via vue like import, parent whatever...)
<el-carousel>
<el-carousel-item>
<p>hello!</p>
</el-carousel-item>
</el-carousel>
And it works... BUT. How i can access to this element? Look to actual slide, use events and so on....?
I was tried in component something like:
import { Carousel } from 'element-ui';
and add to components list... It works, but it is another instance of this class...
So how i can GET real instance of carousel from DOM?
Easy. Make reference on element via ref attribute like this:
<el-carousel ref="myreference"></el-carousel>
and after this access:
console.log(this.$refs.myreference);

"Subclass" a Riot.js template/custom element?

With Riot.js, is there any provision for inheritance with custom elements?
As a trivial example, suppose I have a custom element <custom-button>. Something like this:
<custom-button>
<button>{innerContent}</button>
</custom-button>
Now, maybe I want to sub-class this button as a new custom element, perhaps something that includes an icon:
<custom-button-with-icon>
<inner-content>
{icon} {text}
</inner-content>
<script>
this.extends('custom-button');
</script>
</custom-button-with-icon>
Is there anything like this in Riot.js that allows me to override part of an outer template, or otherwise subclass a custom element?
If you are using Riot.js v4, for subclassing the template/custom component you can use the slot functionality of Riot.js. You create the component with a slot field
<custom-button>
<button>
<slot/>
</button>
</custom-button>
Then you can create another component which uses the custom button
<custom-button-with-icon>
<custom-button>
{icon} {text}
</custom-button>
</custom-button-with-icon>
Then the slot would be replaced with {icon} {text} when the custom-button-with-icon component is used.
More info here: https://riot.js.org/api/#slots

VueJS - sub-nav components outside of router-view?

I have a site layout using Bootstrap as follows (and it needs to stay like this):
<div class='row'>
<div class='col-md-2'>
<main-nav-component></main-nav-component>
<sub-nav-component></sub-nav-component> <!-- Problem Area -->
</div>
<div class='col-md-10'>
<router-view></router-view> <!-- MAIN CONTENT SECTION -->
</div>
</div>
This gives me two columns across the whole site:
A navigation column on the left
A "contents" column on the right
Various pages (but not all) that are displayed in the main content section (via the router-view) also need to display their own sub-nav below the main nav. There are different sub-navs for different pages and I can't figure out how to accomplish this in VueJS. Any ideas?
There's a couple ways of doing this. The easiest is to include the sub header nav components on the components themselves, but you said the above will not change, so instead, you need to pass some kind of data to the sub-nav-component to let it know what to render. One way you can do this is to use the route.
For example, in one application we needed to have a specific sub nav for a group of pages. We have declared a 'zone' in meta, then in the header component we read the zone and display the proper sub-nav for it.
In the router.js:
{
path: '/profile/user',
name: 'Profile',
component: Profile,
meta: { zone: 'profile'}
},
On the header component:
computed: {
zone(){
return this.$store.state.route.meta.zone
},
And in the html of the header component:
<profile-nav v-if="zone == 'profile'"></profile-nav>

Use cases for vue.js directive vs component?

When should I use a directive vs a component in vue.js? I'm implementing some stuff from Bootstrap and it looks like I could do it either way (I'm starting with the dropdown menu).
I get the feeling that a directive is more for manipulating the dom on a single element, while components are for packaging a bunch of data and/or dom manipulation. Is this a good way to look at it?
This Stack Overflow question is the #1 result to the Google query "vue directive vs component". Saurshaz’s answer is currently the accepted one and it’s very wrong in Vue 2.0. I imagine this is leading a lot of people astray so I'm going to weigh in here.
The answer to “should I use a directive or a component in Vue” is almost always a component.
Do you want to have reusable HTML? I.e. reusable widgets? Then use a component. Do you want two of these widgets to have discrete data? Then use a component. The data of one will NOT override the data of another. Maybe that was true in Vue 1.0, I don't know. But it's absolutely not true in Vue 2.0. In Vue 2.0, your components have a data function that returns a unique set of data. Consider this real-life of a Vue dropdown that has an HTML markup similar to the UI Bootstrap dropdown:
<template>
<span class="dropdown sm-dropdown" #click="toggle" :class="{'open': isOpen}">
<a class="dropdown-toggle">
<span class="special-field">{{ label }}</span>
</a>
<ul class="dropdown-menu">
<li v-for="choice in choices">
<a #click.prevent="click(choice)">{{ choice.label }}</a>
</li>
</ul>
</span>
</template>
<script>
export default {
name: 'Dropdown',
props: ['label', 'options', 'onChange'],
data() {
return {
choices: this.options,
isOpen: false
}
},
methods: {
click(option) {
this.onChange(option);
},
toggle() {
this.isOpen = !this.isOpen;
}
}
}
</script>
Now in a parent component, I can do something like this:
<template>
<div class="container">
<dropdown
label="-- Select --"
:options="ratingChoices"
:onChange="toggleChoice"
>
</dropdown>
<dropdown
label="-- Select --"
:options="ratingChoices"
:onChange="toggleChoice"
>
</dropdown>
</div>
</template>
<script>
import Dropdown from '../dropdown/dropdown.component.vue';
export default {
name: 'main-directive',
components: { Dropdown },
methods: {
toggleChoice(newChoice) {
// Save this state to a store, e.g. Vuex
}
},
computed: {
ratingChoices() {
return [{
value: true,
label: 'Yes'
}, {
value: false,
label: 'No'
}]
}
}
}
</script>
There's a decent amount of code here. What's happening is we're setting up a parent component and inside that parent component we have two dropdowns. In other words, the dropdown component is being called twice. The point I'm trying to make in showing this code is this: when you click on the dropdown, the isOpen for that dropdown changes for that directive and for that directive only. Clicking on one of the dropdowns does not affect the other dropdown in any way.
Don't choose between components or directives based on whether or not you're wanting discrete data. Components allow for discrete data.
So when would you want to choose a directive in Vue?
Here are a couple of guidelines that'll hopefully get you thinking in the right direction.
You want to choose a directive when you're wanting to extend the functionality of HTML components and you suspect that you’re going to need this extendability across multiple components and you don't want your DOM to get deeper as a result. To understand what I mean by this, let's look at the directives that Vue provides out of the box. Take its v-for directive for instance. It allows you to loop through a collection. That's very useful and you need to be able to do that in any component you want, and you don't want the DOM to get any deeper. That's a good example of when a directive is the better choice.[1]
You want to choose a directive when you want a single HTML tag to have multiple functionality. For example, an element that both triggers an Ajax request and that has a custom tooltip. Assuming you want tooltips on elements other than Ajax-triggering elements, it makes sense to split these up into two different things. In this example I would make the tooltip a directive and the Ajax feature driven by a component so I could take advantage of the built-in #click directive that’s available in components.
1 A footnote for the more curious. In theory v-for could have been made as a component, but doing so would have required a deeper-than-necessary DOM every time you wanted to use v-for as well as a more awkward syntax. If Vue had chosen to make a component out of it, instead of this:
<a v-for="link in links" :href="link.href">link.anchor</a>
The syntax would have had to have been this:
<v-for items="link in links">
<a :href="link.href">link.anchor</a>
</v-for>
Not only is this clumsy, but since the component code would have needed to implement the <slot></slot> syntax in order to get the innerHTML, and since slots cannot be immediate children of a <template> declaration (since there's no guarantee that slot markup has a single node of entry at its top level), this means there would have to be a surrounding top-level element in the component definition for v-for. Hence the DOM would get deeper than necessary. Directive was unequivocally the right choice here.
I think of it this way:
Components define widgets - these are sections of html that have behavior associated with them.
Directives modify behavior of sections of html (which may or may not be widgets).
I think this difference is better explained with two examples.
Components: are wrappers that are best suited when you need to insert (or add) your own HTML tags over something to render it. E.g. a widget, a custom button, etc where you would need to add some HTML tags to show it properly.
Directives: don't add tags but rather give you direct access to the HTML tag (to which you have added the directive). This gives you access to modify the attributes of that HTML element directly. E.g. initializing a tooltip, set css styles, bind to an event, etc.
Reusability is a reason for using directives,
While Components are also creating reusable 'widgets', two components in the same html system would overwrite the previous ones 'data', So think of directives in a case like this.
Another point worth thinking of is - Can user be using it via HTML only after some instructions ?