I have the following code in my component.ts file on one particular page, because that page needs to use it's own css for when the page is printed:
#Component({
selector: "dashboard",
templateUrl: "./dashboard.component.html",
styleUrls: ["./dashboard.component.scss"],
encapsulation: ViewEncapsulation.None
})
However, when i navigate off that page, i want the encapsulation to go back to normal for everywhere else. Is there a way to do this?
Or is there a way to only set the encapsulation when the print button is clicked? And then when closed it goes back to normal?
If I navigate away from this page and refresh, then the other pages go back to normal, but I don't want to have to refresh.
EDIT
I had to add in the encapsulation in order to get the page to print landscape using this code in the scss file:
#media print {
#page {
size: landscape
}
.no-print,
.no-print * {
display: none !important;
}
body {
-webkit-print-color-adjust: exact;
}
canvas {
max-width: 100%;
height: auto;
}
.printClass {
display: inline-block;
}
}
Otherwise, it would just take the global scss and print portrait every time.
Yes. In this example we use ngx-print. This is a library you can see on GitHub. You do not use it, but it is using the right way and it is very straight forward.
npm install ngx-print
Using
<!--
1)- Add an ID here
-->
<div id="print-section">
<!--Your html stuff that you want to print-->
</div>
<!--
2)- Add the directive name in your button (ngxPrint),
3)- Affect your ID to printSectionId
-->
<button printSectionId="print-section" ngxPrint>print</button>
You can set things in css. Here is a sample:
When I do not apply css using [useExistingCss]="true", the Layout dropdown option (portrait or landscape) is present when trying to print.
My css contains a #media print{#page {size: landscape}} line, but it seems to be ignored by ngx-print.
If I use {size: landscape !important}, it will print in landscape.
If I use {size: auto !important}, the Layout option is provided.
Here is the heart of it:
public print(): void {
let printContents, popupWin, styles = '', links = '';
const baseTag = this.getElementTag('base');
if(this.useExistingCss) {
styles = this.getElementTag('style');
links = this.getElementTag('link');
}
printContents = this.getHtmlContents();
popupWin = window.open("", "_blank", "top=0,left=0,height=auto,width=auto");
popupWin.document.open();
popupWin.document.write(`
<html>
<head>
<title>${this.printTitle ? this.printTitle : ""}</title>
${baseTag}
${this.returnStyleValues()}
${this.returnStyleSheetLinkTags()}
${styles}
${links}
</head>
<body>
${printContents}
<script defer>
function triggerPrint(event) {
window.removeEventListener('load', triggerPrint, false);
${this.previewOnly ? '' : `setTimeout(function() {
closeWindow(window.print());
}, ${this.printDelay});`}
}
function closeWindow(){
window.close();
}
window.addEventListener('load', triggerPrint, false);
</script>
</body>
</html>`);
popupWin.document.close();
I need to extend only several CSS rules in draft-js-emoji-plugin.
Documented way is to pass theme object to configuration:
const theme = {
emojiSelectButton: 'someclassname'
};
const emojiPlugin = createEmojiPlugin({theme});
Unfortunately, this overwrites entire theme classnames instead of adding single one. Based on comments in the code this behavior is by design:
// Styles are overwritten instead of merged as merging causes a lot of confusion.
//
// Why? Because when merging a developer needs to know all of the underlying
// styles which needs a deep dive into the code. Merging also makes it prone to
// errors when upgrading as basically every styling change would become a major
// breaking change. 1px of an increased padding can break a whole layout.
In related issue developers suggested to import draft-js-emoji-plugin/lib/plugin.css and extend it in code. Anyway, each classname in this file has suffixes (CSS modules) and they might be changed so it's reliable.
I don't know how can I apply several fixes without coping entire theme.
a better method would be to import {defaultTheme} from 'draft-js-emoji-plugin' and then extend it as below:
import emojiPlugin, { defaultTheme } from 'draft-js-emoji-plugin';
// say i need to extend the emojiSelectPopover's css then.
defaultTheme.emojiSelectPopover = defaultTheme.emojiSelectPopover + " own-class"
// own class is a class with your required enhanced css. this helps in preserving the old css.
const emojiPlugin = createEmojiPlugin({
theme : defaultTheme
})
and hence use the plugin as you like.
It's nice to have such flexibility, but it really is a pain to rewrite all classes.
What I did was to extract all class names to an object, and with styled-components, interpolated the classNames to the css definition. This way you can extend whatever you want, without worrying about styling a suffixed class (and it changing when they bump a version)
In this gist I've just copied all styles in v2.1.1 of draft-js-emoji-plugin
const theme = {
emoji: 'my-emoji',
emojiSuggestions: 'my-emojiSuggestions',
emojiSuggestionsEntry: 'my-emojiSuggestionsEntry',
// ...
emojiSelect: 'emojiSelect',
emojiSelectButton: 'emojiSelectButton',
emojiSelectButtonPressed: 'emojiSelectButtonPressed',
}
const StyledEmojiSelectWrapper = styled.div`
.${theme.emojiSelect} {
display: inline-block;
}
.${theme.emojiSelectButton}, .${theme.emojiSelectButtonPressed} {
margin: 0;
padding: 0;
width: 2.5em;
height: 1.5em;
box-sizing: border-box;
line-height: 1.2em;
font-size: 1.5em;
color: #888;
background: #fff;
border: 1px solid #ddd;
border-radius: 1.5em;
cursor: pointer;
}
.${theme.emojiSelectButton}:focus, .${theme.emojiSelectButtonPressed}:focus {
outline: 0;
/* reset for :focus */
}
// ...
`
export const GlobalStyleForEmojiSelect = createGlobalStyle`
.${theme.emoji} {
background-position: center;
//...
}
export default (props) => (
<StyledEmojiSelectWrapper>
<GlobalStyleForEmojiSelect />
<EmojiSelect /> // lib button component
</StyledEmojiSelectWrapper>
)
In the html I can use ngStyle to write:
<some-element [ngStyle]="objExp">...</some-element>
Where objExp returns
return {
"background": "red"
};
This works, and turns the background of the element to red.
There are times when I want a fallback values. For example, if I was dealing with gradients I would need -webkit-linear-gradient, -o-linear-gradient then linear-gradient.
I can't add multiple values with the same key to a javascript object.
I guessed at
return { "background": ["red", "blue"] }
but that doesn't seem to work. I've also tried { "background: "red, blue" }
I don't want to use the <some-element [ngStyle]="{'font-style': styleExp}">...</some-element> because that loads complexity repetitively into my html. I can't use [style]="expresionThatGivesAString" because it breaks in Safari.
"red" and "blue" are set at runtime, which is why I'm binding them straight to the element. So putting them in classes isn't an option.
How do I set multiple background values using ngStyle?
For complex rules, use ngClass directive instead. Setup classes in your component styles
component.css
.gradient1 {
background: -webkit-linear-gradient(red, yellow);
background: -o-linear-gradient(red, yellow);
background: -moz-linear-gradient(red, yellow);
}
.gradient2 {
background: -webkit-linear-gradient(black, white);
background: -o-linear-gradient(black, white);
background: -moz-linear-gradient(black, white);
}
Your component should determine which class is active; the class in turn applies the fallback values as defined in the CSS.
component.ts
// Will determine which class to apply.
getClass(){
return someCondition ? 'gradient1' : 'gradient2';
}
Then in your template, just apply the class by binding to the function result.
component.html
<some-element [ngClass]="getClass()">...</some-element>
How can you achieve either a hover event or active event in ReactJS when you do inline styling?
I've found that the onMouseEnter, onMouseLeave approach is buggy, so hoping there is another way to do it.
Specifically, if you mouse over a component very quickly, only the onMouseEnter event is registered. The onMouseLeave never fires, and thus can't update state... leaving the component to appear as if it still is being hovered over. I've noticed the same thing if you try and mimic the ":active" css pseudo-class. If you click really fast, only the onMouseDown event will register. The onMouseUp event will be ignored... leaving the component appearing active.
Here is a JSFiddle showing the problem: https://jsfiddle.net/y9swecyu/5/
Video of JSFiddle with problem: https://vid.me/ZJEO
The code:
var Hover = React.createClass({
getInitialState: function() {
return {
hover: false
};
},
onMouseEnterHandler: function() {
this.setState({
hover: true
});
console.log('enter');
},
onMouseLeaveHandler: function() {
this.setState({
hover: false
});
console.log('leave');
},
render: function() {
var inner = normal;
if(this.state.hover) {
inner = hover;
}
return (
<div style={outer}>
<div style={inner}
onMouseEnter={this.onMouseEnterHandler}
onMouseLeave={this.onMouseLeaveHandler} >
{this.props.children}
</div>
</div>
);
}
});
var outer = {
height: '120px',
width: '200px',
margin: '100px',
backgroundColor: 'green',
cursor: 'pointer',
position: 'relative'
}
var normal = {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'red',
opacity: 0
}
var hover = {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'red',
opacity: 1
}
React.render(
<Hover></Hover>,
document.getElementById('container')
)
Have you tried any of these?
onMouseDown onMouseEnter onMouseLeave
onMouseMove onMouseOut onMouseOver onMouseUp
SyntheticEvent
it also mentions the following:
React normalizes events so that they have consistent properties across different browsers.
The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append Capture to the event name; for example, instead of using onClick, you would use onClickCapture to handle the click event in the capture phase.
The previous answers are pretty confusing. You don't need a react-state to solve this, nor any special external lib. It can be achieved with pure css/sass:
The style:
.hover {
position: relative;
&:hover &__no-hover {
opacity: 0;
}
&:hover &__hover {
opacity: 1;
}
&__hover {
position: absolute;
top: 0;
opacity: 0;
}
&__no-hover {
opacity: 1;
}
}
The React-Component
A simple Hover Pure-Rendering-Function:
const Hover = ({ onHover, children }) => (
<div className="hover">
<div className="hover__no-hover">{children}</div>
<div className="hover__hover">{onHover}</div>
</div>
)
Usage
Then use it like this:
<Hover onHover={<div> Show this on hover </div>}>
<div> Show on no hover </div>
</Hover>
you can use onMouseOver={this.onToggleOpen} and onMouseOut={this.onToggleOpen} to muse over and out on component
Note: This answer was for a previous version of this question where the question asker was trying to use JavaScript to apply css styles… which can simply be done with CSS.
A simple css-only solution.
For applying basic styles, CSS is simpler and more performant that JS solutions 99% of the time. (Though more modern CSS-in-JS solutions — eg. React Components, etc — are arguably more maintainable.)
Run this code snippet to see it in action…
.hover-button .hover-button--on,
.hover-button:hover .hover-button--off {
display: none;
}
.hover-button:hover .hover-button--on {
display: inline;
}
<button class='hover-button'>
<span class='hover-button--off'>Default</span>
<span class='hover-button--on'>Hover!</span>
</button>
If you can produce a small demo showing the onMouseEnter / onMouseLeave or onMouseDown / onMouseUp bug, it would be worthwhile to post it to ReactJS's issues page or mailing list, just to raise the question and hear what the developers have to say about it.
In your use case, you seem to imply that CSS :hover and :active states would be enough for your purposes, so I suggest you use them. CSS is orders of magnitude faster and more reliable than Javascript, because it's directly implemented in the browser.
However, :hover and :active states cannot be specified in inline styles. What you can do is assign an ID or a class name to your elements and write your styles either in a stylesheet, if they are somewhat constant in your application, or in a dynamically generated <style> tag.
Here's an example of the latter technique: https://jsfiddle.net/ors1vos9/
I've just bumped into this same problem when listening for onMouseLeave events on a disabled button. I worked around it by listening for the native mouseleave event on an element that wraps the disabled button.
componentDidMount() {
this.watchForNativeMouseLeave();
},
componentDidUpdate() {
this.watchForNativeMouseLeave();
},
// onMouseLeave doesn't work well on disabled elements
// https://github.com/facebook/react/issues/4251
watchForNativeMouseLeave() {
this.refs.hoverElement.addEventListener('mouseleave', () => {
if (this.props.disabled) {
this.handleMouseOut();
}
});
},
render() {
return (
<span ref='hoverElement'
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
>
<button disabled={this.props.disabled}>Submit</button>
</span>
);
}
Here's a fiddle https://jsfiddle.net/qfLzkz5x/8/
I'd use onMouseOver & onMouseOut. Cause in React:
The onMouseEnter and onMouseLeave events propagate from the element being left to the one being entered instead of ordinary bubbling and do not have a capture phase.
Here it is in the React documentation for mouse events.
A package called styled-components can solve this problem in an ELEGANT way.
Reference
Glen Maddern - Styling React Apps with Styled Components
Example
const styled = styled.default
const Square = styled.div`
height: 120px;
width: 200px;
margin: 100px;
background-color: green;
cursor: pointer;
position: relative;
&:hover {
background-color: red;
};
`
class Application extends React.Component {
render() {
return (
<Square>
</Square>
)
}
}
/*
* Render the above component into the div#app
*/
ReactDOM.render(<Application />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js"></script>
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
<div id='app'></div>
You can't with inline styling alone. Do not recommend reimplementing CSS features in JavaScript we already have a language that is extremely powerful and incredibly fast built for this use case -- CSS. So use it! Made Style It to assist.
npm install style-it --save
Functional Syntax (JSFIDDLE)
import React from 'react';
import Style from 'style-it';
class Intro extends React.Component {
render() {
return Style.it(`
.intro:hover {
color: red;
}
`,
<p className="intro">CSS-in-JS made simple -- just Style It.</p>
);
}
}
export default Intro;
JSX Syntax (JSFIDDLE)
import React from 'react';
import Style from 'style-it';
class Intro extends React.Component {
render() {
return (
<Style>
{`
.intro:hover {
color: red;
}
`}
<p className="intro">CSS-in-JS made simple -- just Style It.</p>
</Style>
}
}
export default Intro;
Use Radium!
The following is an example from their website:
var Radium = require('radium');
var React = require('react');
var color = require('color');
#Radium
class Button extends React.Component {
static propTypes = {
kind: React.PropTypes.oneOf(['primary', 'warning']).isRequired
};
render() {
// Radium extends the style attribute to accept an array. It will merge
// the styles in order. We use this feature here to apply the primary
// or warning styles depending on the value of the `kind` prop. Since its
// all just JavaScript, you can use whatever logic you want to decide which
// styles are applied (props, state, context, etc).
return (
<button
style={[
styles.base,
styles[this.props.kind]
]}>
{this.props.children}
</button>
);
}
}
// You can create your style objects dynamically or share them for
// every instance of the component.
var styles = {
base: {
color: '#fff',
// Adding interactive state couldn't be easier! Add a special key to your
// style object (:hover, :focus, :active, or #media) with the additional rules.
':hover': {
background: color('#0074d9').lighten(0.2).hexString()
}
},
primary: {
background: '#0074D9'
},
warning: {
background: '#FF4136'
}
};
I had a similar issue when onMouseEnter was called but sometimes the corresponding onMouseLeave event wasn't fired, here is a workaround that works well for me (it partially relies on jQuery):
var Hover = React.createClass({
getInitialState: function() {
return {
hover: false
};
},
onMouseEnterHandler: function(e) {
this.setState({
hover: true
});
console.log('enter');
$(e.currentTarget).one("mouseleave", function (e) {
this.onMouseLeaveHandler();
}.bind(this));
},
onMouseLeaveHandler: function() {
this.setState({
hover: false
});
console.log('leave');
},
render: function() {
var inner = normal;
if(this.state.hover) {
inner = hover;
}
return (
<div style={outer}>
<div style={inner}
onMouseEnter={this.onMouseEnterHandler} >
{this.props.children}
</div>
</div>
);
}
});
See on jsfiddle: http://jsfiddle.net/qtbr5cg6/1/
Why was it happening (in my case): I am running a jQuery scrolling animation (through $('#item').animate({ scrollTop: 0 })) when clicking on the item. So the cursor doesn't leave the item "naturally", but during a the JavaScript-driven animation ... and in this case the onMouseLeave was not fired properly by React (React 15.3.0, Chrome 51, Desktop)
I know It's been a while since this question was asked but I just run into the same issue of inconsistency with onMouseLeave()
What I did is to use onMouseOut() for the drop-list and on mouse leave for the whole menu, it is reliable and works every time I've tested it.
I saw the events here in the docs: https://facebook.github.io/react/docs/events.html#mouse-events
here is an example using https://www.w3schools.com/bootstrap/bootstrap_dropdowns.asp:
handleHoverOff(event){
//do what ever, for example I use it to collapse the dropdown
let collapsing = true;
this.setState({dropDownCollapsed : collapsing });
}
render{
return(
<div class="dropdown" onMouseLeave={this.handleHoverOff.bind(this)}>
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Dropdown Example
<span class="caret"></span></button>
<ul class="dropdown-menu" onMouseOut={this.handleHoverOff.bind(this)}>
<li>bla bla 1</li>
<li>bla bla 2</li>
<li>bla bla 3</li>
</ul>
</div>
)
}
I personally use Style It for inline-style in React or keep my style separately in a CSS or SASS file...
But if you are really interested doing it inline, look at the library, I share some of the usages below:
In the component:
import React from 'react';
import Style from 'style-it';
class Intro extends React.Component {
render() {
return (
<Style>
{`
.intro {
font-size: 40px;
}
`}
<p className="intro">CSS-in-JS made simple -- just Style It.</p>
</Style>
);
}
}
export default Intro;
Output:
<p class="intro _scoped-1">
<style type="text/css">
._scoped-1.intro {
font-size: 40px;
}
</style>
CSS-in-JS made simple -- just Style It.
</p>
Also you can use JavaScript variables with hover in your CSS as below :
import React from 'react';
import Style from 'style-it';
class Intro extends React.Component {
render() {
const fontSize = 13;
return Style.it(`
.intro {
font-size: ${ fontSize }px; // ES2015 & ES6 Template Literal string interpolation
}
.package {
color: blue;
}
.package:hover {
color: aqua;
}
`,
<p className="intro">CSS-in-JS made simple -- just Style It.</p>
);
}
}
export default Intro;
And the result as below:
<p class="intro _scoped-1">
<style type="text/css">
._scoped-1.intro {
font-size: 13px;
}
._scoped-1 .package {
color: blue;
}
._scoped-1 .package:hover {
color: aqua;
}
</style>
CSS-in-JS made simple -- just Style It.
</p>
Hover is a CSS feature; it comes with the CSS side of the app so do it the right way is so much fun. Simply put, when I require a hover effect on an element in the React app, first, I create a class in my CSS file and then I add the created class into the className of the element. The steps I follow are:
Create a CSS file unless you have index.css
Create a class with a hover pseudo-class enabled
.hover__effect:hover {}
Add the effects you require
.hover__effect:hover {
background-color: rgb(255, 255, 255);
color: rgb(0, 0, 0);
}
Then add the hover__effect to the class's component that should be different when the mouse pointer hovers over it
Hover
Please check my sandbox for a live demo.
Hello I am using jquery layout plugin from http://layout.jquery-dev.net/ .
my options are following:
<script>
$(document).ready(function(){
// create page layout
pageLayout = $('body').layout(
{applyDemoStyles: true,
spacing_open:0,
spacing_closed: 0,
slidable: false,
togglerLength_closed: 0
});
pageLayout.panes.north.css('backgroundColor','#A6f');
// we need to remove the borders as well....
});
</script>
This removes sliders but:
How to remove the pane borders as well?
thanks Arman.
Remove one border:
pageLayout.panes.north.css('border','none');
Remove all borders:
As you should be quite sure that each pageLayout.pane will have o as a property:
for(property in pageLayout.panes){
pageLayout.panes[property].css('border', 'none');
}
How you should really do it - checks to make sure o is a property of pageLayout.pane before attempting to access it:
for(property in pageLayout.panes){
if(pageLayout.panes.hasOwnProperty(property)){
pageLayout.panes[property].css('border', 'none');
}
}
I haven't tried this plugin yet but since your last line is pretty much like the usual css try this.
pageLayout.panes.north.css({'backgroundColor' : '#A6f', 'border' : 'none'});
Using a css rewriting. After including the css layout file in the head section (usually jquery.ui.layout.css) you could add a style that rewrites the original.
<style>
.ui-layout-pane {
background: #FFF;
border: 0 none; //This rewrites the original style
padding: 10px;
overflow: auto;
}
</style>