I have two components:
LoginLayout which should is high order comp for Login component
Login component is page
I need to make the login page have an image as the background.
I tried achieving this through CSS and it does not work.
Here is LoginLayout comp:
export default ({ children, title }) => (
// I tried to add background: url(.../img)) to this login-layout class
<div className="login-layout">
<Head>
<title>Login to Tex</title>
</Head>
<div className="login-wrapper">{children}</div>
</div>
);
How can this be achieved in Next.js?
Make sure you have your CSS attached to your component, as #Deano mentioned.
import './style.css';
If you use CSS modules import like this instead:
import styles from './MyStyles.module.css';
export default ({ children, title }) => (
<div className={styles.loginLayout}>
<Head>
<title>Login to Tex</title>
</Head>
<div className={styles.Login-wrapper}>{children}</div>
</div>
);
Related
I have following code:
// App.js
useEffect(() => {
ReactTooltip.rebuild()
}, [])
// index.html
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="tooltip" data-for="tooltipStep" data-tip="tooltipStep_1"></div>
<div id="root"></div>
</body>
// MyTooltip.js
import ReactTooltip from "react-tooltip";
import ReactDOM from "react-dom";
import React from "react";
import classes from './MyTooltip.module.css';
const MyTooltip = (props) =>
<React.Fragment>
{
ReactDOM.createPortal(
<div>
<div className={classes.backdrop} />
<ReactTooltip
id={props.id}
type="dark"
place={props.place}
className={classes.tooltip}
>
<span>{props.text}</span>
</ReactTooltip>
</div>
,
document.getElementById("tooltip")
)}
</React.Fragment>
export default MyTooltip;
The problem is that when I unmaximize the browser window, tooltip disappears when cursor is positioned beyond the browser window. Also tooltip disappears if scrolling occurs. I have to point cursor to the navigation bar and then back to the webapp for tooltip to show up again after scrolling.
How could I make react-tooltip always visible no matter what?
Thanks in advance.
React tooltip comes with different attribute that includes scrollHide (default is true) and resizeHide (default is true).
You can just set them to false;
<ReactTooltip
id={props.id}
type="dark"
place={props.place}
scrollHide={false}
resizeHide={false}
className={classes.tooltip}
>
<span>{props.text}</span>
</ReactTooltip>
No errors in browser, Webpack compiles successfully, but the "hello from dashboard" doesn't show up in the page.
I'm using Vue v2.6
main.js
import Vue from 'vue'
Vue.component('dashboard', require('#comp/dashboard.vue').default);
const app = require('#/App.vue').default; // this app component works fine
import "./css/app.css"
new Vue({
render: h => h(app) // this app component works fine
}).$mount('#app')
dashboard.vue
<template>
<div>
Hello from dashboard
</div>
</template>
<script>
export default {
name: "dashboard"
}
</script>
index.html
<body>
<div id="app">
<dashboard></dashboard>
</div>
</body>
This is the rendered HTML from the browser, However, "hello from dashboard" is not there :(
<body>
<div id="app">
<dashboard></dashboard>
</div>
</body>
You have the root file "App.vue" mounted in the div id = "app", so the "dashboard" needs to be added to App.vue to see its contents.
// App.vue
<template>
<dashboard />
</template>
<script>
export default {};
</script>
<style scoped></style>
In this code, you have connected a component globally, which will be available in App.vue or another child component
Vue.component('dashboard', require('#comp/dashboard.vue').default);
I assume its the path you are missing so i added a / before comp. Because you stated the App.vue works.
Vue.component('dashboard', require('#/comp/dashboard.vue').default);
When I add a wrapper to this jsx, it breaks the existing CSS and I can't determine why. The page CSS is proper at first, but this wrapper causes the menu-item s to shrink. What am I missing here?
Before:
import React from "react";
import { withRouter } from "react-router-dom";
import "./menu-item.styles.scss";
const MenuItem = ({ title, imageUrl, size, history, match }) => (
<div className={`${size} menu-item`}>
<div
className="background-image"
style={{
backgroundImage: `url(${imageUrl})`,
}}
/>
<div className="content">
<h1 className="title">{title.toUpperCase()} </h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
);
export default withRouter(MenuItem);
After:
import React from "react";
import { withRouter } from "react-router-dom";
import "./menu-item.styles.scss";
const MenuItem = ({ title, imageUrl, size, history, match }) => (
<a href="https://www.google.com">
<div className={`${size} menu-item`}>
<div
className="background-image"
style={{
backgroundImage: `url(${imageUrl})`,
}}
/>
<div className="content">
<h1 className="title">{title.toUpperCase()} </h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
</a>
);
export default withRouter(MenuItem);
The browsers generally add their own style to the anchor tag, and the tag also inherits some style from the body and whatnot. What you need to do is make apply some CSS of your own to the anchor to make sure it's always extended like a wrapper.
Maybe something like this should help.
#mainMenu a {
display: inline-block;
width: 100%; //depending if your menu direction is in rows or columns
}
If your menu item also has some padding, I suggest moving that padding to the anchor as well.
Anyhow, you can always toy around with the CSS applied to your anchor tag if you inspect the element (Right Click -> Inspect). Let me know if you have more questions about this.
I'm trying to use slots to inject content from a parent component to its child, but Vue keeps rendering the default content, not parsing the content sent from its parent.
This is the code of the parent component, which in turn is a child of a global component:
let parentComponent = {
template: `
<div>
<child-component>
<template v-slot:action>Close</template>
<template v-slot:element>Modal</template>
</child-component>
</div>
`,
components: {
'child-component': childComponent
}
};
And here is its child component, where I want to pass content:
let childComponent = {
template: `
<button>
<slot name="action">Open</slot>
<slot name="element">Window</slot>
</button>
`,
};
The button is still displaying the default content: "Open Window"
What am I doing wrong?
EDIT:
This is the rest of the content, just in case it helps:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VueJS</title>
</head>
<body>
<div id="app">
<vue-directives></vue-directives>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<script src="components/slotDirective/slotDirectiveSubcomponent.js"></script>
<script src="components/slotDirective/slotDirective.js"></script>
<script src="components/VueDirectives.js"></script>
<script>
let vue = new Vue({
el: '#app'
});
</script>
</body>
</html>
And VueDirectives.js:
Vue.component('vue-directives', {
template: `
<div>
<h3>{{ title }}</h3>
<parentComponent/>
</div>
`,
data() {
return {
title: "VueJS directives",
}
},
components: {
parentComponent
}
});
I fixed the error. I don't know the reason, but it wasn't working either if I loaded Vue.js from a CDN, or if I manually downloaded it locally, as a single file.
Then I finally tried installing it from npm, and loading Vue.js in node_modules/vue/dist/vue.js, and this way it works. I assume otherwise Vue.js does not comply with all its functionality.
I'm not sure that slots are designed for this. If you are just changing the text of a button passing props into the parentComponent is how i would go about it. E.g.
<parentComponent buttonText="some text or bind with a data value or computed prop"/>
see: https://v2.vuejs.org/v2/guide/components-props.html
Using slots... If you are experimenting try this, a reusable dialog box that you can pop in anywhere and control the content. E.g.
// myDialog
<v-dialog>
<slot>Here you can put what you want</slot>
</v-dialog>
And to use:
<myDialog>
<template>
<myContent /> Or just put content here without another component
</template>
</myDialog>
main.js file:
import Vue from 'vue'
import App from './App.vue'
import Parent from './assets/components/frame/Parent.vue';
import LeftSide from './assets/components/frame/LeftSide.vue';
import RightSide from './assets/components/frame/RightSide.vue';
import HeaderLeft from './assets/components/header/HeaderLeft.vue';
import HeaderRight from './assets/components/header/HeaderRight.vue';
Vue.component('Parent', Parent);
Vue.component('LeftSide', LeftSide);
Vue.component('RightSide', RightSide);
Vue.component('HeaderLeft', HeaderLeft);
Vue.component('HeaderRight', HeaderRight);
new Vue({
el: '#app',
render: h => h(App)
})
Non working app.vue file, no data appears on web page. When examining the page via dev tools, the parent div is there, but it's empty. I'm expecting the LeftSide and RightSide to be nested inside of it.
<template>
<div>
<Parent>
<LeftSide>
</LeftSide>
<RightSide>
</RightSide>
</Parent>
</div>
</template>
<script>
</script>
<style>
</style>
When modified to the below (exclude 'Parent'), to have no nested components, the data (left side and right side) outputs to the web page fine.
<template>
<div>
<LeftSide>
</LeftSide>
<RightSide>
</RightSide>
</div>
</template>
<script>
</script>
<style>
</style>
Parent component below
<template>
<div class="parent">
</div>
</template>
<script>
</script>
<style>
.parent
{
display: flex;
}
</style>
I fixed it by moving LeftSide and RightSide into the Parent.vue, instead of having the LeftSide and RightSide inside the Parent in the app.vue.
As you already figured out yourself you should move those components into the Parent component.
But there are situations where you want to have a reusable component as decorator (something like a panel) and place elements inside of it. In this case you are looking for slots. Using slot you can indeed write this:
<Parent>
<LeftSide />
<RightSide />
</Parent>
And in the Parent component you would need to define where those components have to be placed using <slot></slot>
<template>
<div class="parent">
<slot></slot>
</div>
</template>
<script>
</script>
<style>
.parent
{
display: flex;
}
</style>