how to style HTML when using react-native-print - reactjs

So what I am trying to print out html but with little styling i tried everything that i know of but I was't able to get it done.Every thing is working fine thought can't style the Html.I even tried to bind it with the style tag properties but still it didn't worked.
My code is
import React, { Component } from 'react';
import {
AppRegistry,
Button,
StyleSheet,
NativeModules,
Platform,
Text,
View
} from 'react-native';
import RNPrint from 'react-native-print';
export default class RNPrintExample extends Component {
state = {
selectedPrinter: null
}
// #NOTE iOS Only
selectPrinter = async () => {
const selectedPrinter = await RNPrint.selectPrinter()
this.setState({ selectedPrinter })
}
// #NOTE iOS Only
silentPrint = async () => {
if (!this.state.selectedPrinter) {
alert('Must Select Printer First')
}
const jobName = await RNPrint.print({
printerURL: this.state.selectedPrinter.url,
html: '<h1>Silent Print</h1>'
})
}
//trying to style this HTML
async printHTML() {
await RNPrint.print({
html: '<h1>Heading 1</h1><h2>Heading 2</h2><h3>Heading 3</h3>'
})
}
async printRemotePDF() {
await RNPrint.print({ filePath: 'https://graduateland.com/api/v2/users/jesper/cv' })
}
customOptions = () => {
return (
<View>
{this.state.selectedPrinter &&
<View>
<Text>{`Selected Printer Name: ${this.state.selectedPrinter.name}`}</Text>
<Text>{`Selected Printer URI: ${this.state.selectedPrinter.url}`}</Text>
</View>
}
<Button onPress={this.selectPrinter} title="Select Printer" />
<Button onPress={this.silentPrint} title="Silent Print" />
</View>
)
}
render() {
return (
<View style={styles.container}>
{Platform.OS === 'ios' && this.customOptions()}
<Button onPress={this.printHTML} title="Print HTML" />
<Button onPress={this.printPDF} title="Print PDF" />
<Button onPress={this.printRemotePDF} title="Print Remote PDF" />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
});
Any help Would be Appreciated.

<html>
<head>
<style>
.heading{
background-color: red;
}
.block {
background-color: black;
height: 30;
}
.text{
color: white;
}
</style>
</head>
<body>
<h1 class='heading'>Title</h1>
<div class='block'>
<span class='text'>Hello, World !</span>
</div>
</body>
I was able to style it by storing the above HTML inside back-ticks (``) and using it like
RNPrint.print({
html: `<html>... ....</html>`
})

you can use this as a guide. worked well for me.
<page size="A4"></page>
<page size="A4"></page>
<page size="A4" layout="landscape"></page>
<page size="A5"></page>
<page size="A5" layout="landscape"></page>
<page size="A3"></page>
<page size="A3" layout="landscape"></page>
body {
background: rgb(204,204,204);
}
page {
background: white;
display: block;
margin: 0 auto;
margin-bottom: 0.5cm;
box-shadow: 0 0 0.5cm rgba(0,0,0,0.5);
}
page[size="A4"] {
width: 21cm;
height: 29.7cm;
}
page[size="A4"][layout="landscape"] {
width: 29.7cm;
height: 21cm;
}
page[size="A3"] {
width: 29.7cm;
height: 42cm;
}
page[size="A3"][layout="landscape"] {
width: 42cm;
height: 29.7cm;
}
page[size="A5"] {
width: 14.8cm;
height: 21cm;
}
page[size="A5"][layout="landscape"] {
width: 21cm;
height: 14.8cm;
}
#media print {
body, page {
margin: 0;
box-shadow: 0;
}
}
https://codepen.io/rafaelcastrocouto/pen/LFAes

Related

StopPropagation react google maps autocomplete

I would like to stopPropagation of https://react-google-maps-api-docs.netlify.app/#autocomplete.
The autocomplete works well but I need to use it in a popover and when I select a place the popover automatically closes.
If there is another library that works well with popovers and modals
const [autocomplete, setAutocomplete] = useState<any>(null);
const onLoad = (auto: any) => {
if (!autocomplete) {
setAutocomplete(auto);
}
};
const onPlaceChanged = () => {
if (autocomplete) {
console.log(autocomplete?.getPlace());
} else {
console.log('Autocomplete is not loaded yet!');
}
};
<Autocomplete
onLoad={onLoad}
onPlaceChanged={onPlaceChanged}
>
<chakra.input
type='text'
as={Input}
placeholder='Customized your placeholder'
style={{
boxSizing: `border-box`,
border: `1px solid transparent`,
width: `240px`,
height: `32px`,
padding: `0 12px`,
borderRadius: `3px`,
boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
fontSize: `14px`,
outline: `none`,
textOverflow: `ellipses`,
position: 'absolute',
left: '50%',
marginLeft: '-120px',
animationName: 'none',
zIndex: 9999,
}}
/>
</Autocomplete>
I'm using chakraUI, I get help from discord(dodas user) here is the solution he make. Basically he catch the mousedown event(google block click event) and when the popover is open, select item or click trigger button just do nothing for others events just close popovers.
https://codesandbox.io/s/popovergoogle-autocomplete-6nvtb?file=/src/App.js:0-3329
import React, { useState, useEffect, useRef } from "react";
import {
Button,
Stack,
Popover,
PopoverTrigger,
PopoverContent,
PopoverHeader,
PopoverBody,
PopoverArrow,
PopoverCloseButton,
Box,
Portal,
PopoverFooter,
useRadioGroup,
useRadio
} from "#chakra-ui/core";
import { useEvent } from "react-use";
import {
GoogleMap,
useJsApiLoader,
Autocomplete
} from "#react-google-maps/api";
let autoComplete;
export function App() {
const { isLoaded, loadError } = useJsApiLoader({
googleMapsApiKey: "YOUR_KEY", // ,
libraries: ["places"]
// ...otherOptions
});
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const openPopover = () => setIsPopoverOpen(true);
const closePopover = () => setIsPopoverOpen(false);
const triggerRef = useRef(null);
const popoverContentRef = useRef(null);
const [autocomplete, setAutocomplete] = useState(null);
const onLoad = (autocompleteInstance) => {
console.log("autocomplete: ", autocomplete);
setAutocomplete(autocompleteInstance);
};
const onPlaceChanged = () => {
if (autocomplete) {
console.log(autocomplete.getPlace());
} else {
console.log("Autocomplete is not loaded yet!");
}
};
useEvent("mousedown", (ev) => {
if (!isPopoverOpen) {
return;
}
const clickedInsideTrigger = triggerRef.current.contains(ev.target);
const clickedInsidePopover = popoverContentRef.current.contains(ev.target);
const clickedInsideAutocomplete =
ev.target.closest(".pac-container") != null;
if (
clickedInsideTrigger ||
clickedInsidePopover ||
clickedInsideAutocomplete
) {
return;
}
closePopover();
});
return (
<>
<Box width="100vw" height="100vh">
<Popover
isOpen={isPopoverOpen}
onOpen={openPopover}
onClose={closePopover}
closeOnBlur={false}
isLazy
placement="bottom-end"
>
<PopoverTrigger>
<Button ref={triggerRef}>Trigger</Button>
</PopoverTrigger>
<PopoverContent ref={popoverContentRef}>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader>Confirmation!</PopoverHeader>
<PopoverBody minH="20rem">
{isLoaded && (
<Autocomplete onLoad={onLoad} onPlaceChanged={onPlaceChanged}>
<input
type="text"
placeholder="Customized your placeholder"
style={{
boxSizing: `border-box`,
border: `1px solid transparent`,
width: `240px`,
height: `32px`,
padding: `0 12px`,
borderRadius: `3px`,
boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
fontSize: `14px`,
outline: `none`,
textOverflow: `ellipses`,
position: "absolute",
left: "50%",
marginLeft: "-120px"
}}
/>
</Autocomplete>
)}
</PopoverBody>
</PopoverContent>
</Popover>
</Box>
</>
);
}

React-select, open sub-menu when hover over an option

I'm trying to build a submenu inside a main menu with React-select, it should be something like this:
When hovering over an option from the main menu, it triggers the submenu to open at the side.
Is there a way to do this using react-select? I couldn't find any example or documentation on this, is there a function like ```optionOnMouseover`` for this? Thank you in advance!
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
];
...
<Select
value={...}
onChange={...}
options={options}
/>```
This is on click, but if you need on hover,
just modify it
import React, { useState } from "react";
import ReactDOM from "react-dom";
import Select, { components } from "react-select"
const CustomOption = (props) => {
const [submenu, setSubmenu] = useState(false)
const [height, setHeight] = useState(0)
const handleOption = (e) => {
if(submenu) {
setSubmenu(false)
} else {
setHeight(e.clientY)
setSubmenu(true)
}
}
const handleSubOption = (e) => {
console.log('clicked')
}
const { data } = props;
return data.custom ? (
<>
<div onClick={handleOption} className="customs">
{data.label} <span className="caret"/>
{
submenu && (
<div className="dropdown-submenu">
<div className="drops" onClick={handleSubOption}>
Test dropdown 1
</div>
<div className="drops" onClick={handleSubOption}>
Test dropdown 2
</div>
<div className="drops" onClick={handleSubOption}>
Test dropdown 3
</div>
</div>
)
}
</div>
<style jsx>{`
.customs {
height: 36px;
padding: 8px;
position: relative;
}
.drops {
height: 36px;
padding: 8px;
}
.customs:hover, .drops:hover {
background-color: #17cf76;
}
.dropdown-submenu {
position: fixed;
top: ${height - 10}px;
left: 410px;
min-height: 36px;
overflow: auto;
border: 1px solid hsl(0,0%,80%);
border-radius: 4px;
color: #212529;
}
`}</style>
</>
) : (
<components.Option {...props} />
);
};
const options = [
{ custom: true, label: "I'm a custom link", value: "cust" }
];
function App() {
return (
<>
<Select classNamePrefix="category-select" className="w-30" components={{ Option: CustomOption }} options={options} />
<style jsx global>{`
* {
font-family: sans-serif;
text-align: center;
}
.w-30 {
width: 30% !important;
}
`}</style>
</>
)
}
export default App

react map leaflet circleMarker doesn't render

I have a leaflet map, and I have one button. I want to display some circlesMarker when I click on a button and remove the circlesMarker when I click again (remove option is not implemented yet)
I don't want to render each time all map when I click the button, I want render only the circleMarker.
CircleMarker doesn't render on a map, but I can see the map
Here my code :
COMPONENT MAP
function Map1() {
const apartments = [
{ roomType: 'shared room', geometry: [41.402610, 2.204270] },
{ roomType: 'shared room', geometry: [41.411300, 2.217630] },
{ roomType: 'private room', geometry: [41.410220, 2.212520] },
{ roomType: 'apartament sencer', geometry: [41.410630, 2.216970] },
{ roomType: 'private room', geometry: [41.409190, 2.209030] },
]
let map = useRef(null);
useEffect(() => {
let url = 'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}'
const access = 'pk.eyJ1Ijoiam9zZXQyMSIsImEiOiJjazF1bGZlcHowYjVlM2RwYW9ia2pwaWtlIn0.9n-6tKArfdSfd15Do6YxLA'
map.current = L.map("map");
const defaultCenter = [41.383, 2.173];
const defaultZoom = 13.10;
let layer = L.tileLayer(url, {
maxZoom: 18,
id: 'mapbox.streets',
accessToken: access,
});
map.current.setView(defaultCenter, defaultZoom);
layer.addTo(map.current);
}, [map])
const handleOnclik = (e) => {
e.preventDefault()
let color = (e.target.name)
if (color === 'pink') {
apartments.map(item => {
if (item.roomType === 'private room' || item.roomType === 'shared room') {
return (
<div>
<p>Carme</p>
<CircleMarker className="circle"
center={[41.409190, 2.209030]}
color={'#000080'}
width={.5}
fillColor={'blue'}
fillOpacity={0.5}
stroke={'black'}
>
</CircleMarker >
</div>
)
}
})
}
return (<>
<div className="container">
<div>
<div id="map" className="normalscreen"></div>
</div>
<div id="basemaps-wrapper" className="leaflet-bar">
<select id="basemaps">
<option>Visualització</option>
<option value="mapbox.streets">Streets</option>
<option value="mapbox.satellite">Satellite</option>
<option value="mapbox.outdoors">Outdoors</option>
<option value="mapbox.dark">Dark</option>
<option value="mapbox.light">Light</option>
<option value="mapbox.DarkGray">Dark Gray</option>
</select>
<button onClick={onChangeFullScreen}>Full Screen</button>
<div>
<img onClick={handleOnclik} name="pink" src="images/pink" alt="habitacio" />
<img onClick={handleOnclik} name="green" src="images/green" alt="apartament" />
</div>
</div>
</div>
</>)
}
export default Map1
MAP CSS
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: column;
width: 100vw;
justify-content: center;
}
#map {
display: block;
}
.normalscreen {
width: 50%;
height: 50vh;
left: 49%;
position: relative;
}
.fullscreen {
width: 100%;
height: 80vh;
left: 0%;
text-align: center;
}
APP
import React from 'react'
import { withRouter } from 'react-router-dom'
import Navbar from './Navbar'
import Map from './Map'
function App() {
return (<>
<Navbar />
<Map />
</>);
}
export default withRouter(App)
There is no CircleMarker component on leaflet library exposed unless you use react-leaflet which you don't. Therefore here is the code you need to use in order to add to the map circle markers:
const handleOnclik = () => {
apartments.forEach(({ geometry }) => {
new L.CircleMarker(geometry, {
radius: 5,
fillColor: "blue",
width: 0.5,
stroke: "black",
color: "#000080",
fillOpacity: 0.5
}).addTo(map.current);
});
};
I removed the if statements for simplicity just to illustrate an example.
Demo

How to delay a component render in React?

I have an instagram widget thas uses iframe, but when I switch between routes, the widget loads too slow and does'nt have time to render properly.
Can You tell me, how to set delay rendering of the component, jr another solution to this problem?
Here is the component:
import React, { Component } from 'react';
const divStyle = [
{
border: 'none',
overflow: 'hidden',
width: '100%'
},
{
font: "10px/14px 'Roboto','Helvetica Neue',Arial,Helvetica,sans-serif",
fontWeight: '400',
width: '100%',
textAlign: 'right'
},
{
color: '#777',
textDecoration: 'none'
}
];
class Instagram extends Component {
render() {
return (
<div id="instagram">
<iframe src="https://snapwidget.com/embed/711808" className="snapwidget-widget" allowtransparency="true" frameborder="0" scrolling="no" style={divStyle[0]}></iframe>
</div>
);
}
}
export default Instagram;
Also the code is located in the CodeSandbox.
Thanks for any help!
This can be possible solution from your code sandbox.
NOTE: Please Replace your loader with loading div.
CodeSandbox: https://codesandbox.io/s/damp-platform-950yw
import React, { Component } from "react";
const divStyle = [
{
border: "none",
overflow: "hidden",
width: "100%"
},
{
font: "10px/14px 'Roboto','Helvetica Neue',Arial,Helvetica,sans-serif",
fontWeight: "400",
width: "100%",
textAlign: "right"
},
{
color: "#777",
textDecoration: "none"
}
];
class Instagram extends Component {
state = {
loading: true
}
handelOnLoad = () => {
this.setState({
loading: false
})
}
render() {
return (
<>
{this.state.loading && <div style={{
position: "fixed",
background: "rgba(0,0,0,0.7)",
top: 0,
bottom: 0,
right: 0,
left: 0,
color: "#fff"
}}>Loading</div>}
<div id="instagram">
<iframe
src="https://snapwidget.com/embed/711808"
className="snapwidget-widget"
allowtransparency="true"
frameborder="0"
scrolling="no"
style={divStyle[0]}
onLoad={this.handelOnLoad}
/>
</div>
</>
);
}
}
export default Instagram;
You can make use of state to render,
class Instagram extends Component {
state={
show: false
}
componentDidMount(){
setTimeout(()=>{
this.setState({show: true})
},5000) //runs after 5sec
}
render() {
return (
<div id="instagram">
{ this.state.show && <iframe src="https://snapwidget.com/embed/711808" className="snapwidget-widget" allowtransparency="true" frameborder="0" scrolling="no" style={divStyle[0]}></iframe> }
</div>
);
}
}

React menu item hover

I am trying React MobX on hover over a list item. Here is my code
export default observer(
class SidebarContent extends React.Component {
constructor(props) {
super(props);
}
componentWillMount() {
this.props.store.fetchSources()
}
toggleHover(){
this.props.store.hover = !this.props.store.hover;
}
getArticles(src) {
this.props.store.fetchArticles(src);
}
render() {
const style1 = this.props.style ? {...styles.sidebar, ...this.props.style} : styles.sidebar;
const { sources, hover } = this.props.store
var linkStyle;
if (this.props.store.hover) {
linkStyle = {backgroundColor: 'black'}
} else {
linkStyle = {backgroundColor: 'white'}
}
const links = sources.map( (src,index) => (
<a key={index} href='javascript:;' style={styles.sidebarLink} onClick={this.getArticles.bind(this, src.id)} >
<span style={linkStyle} onMouseEnter={this.toggleHover.bind(this)} onMouseLeave={this.toggleHover.bind(this)} >
<img className="ui-avaatar image" src='{ src.urlsToLogos.small }' />
<span className="side-news-item"> {src.name} </span>
</span>
</a>
))
return (
<MaterialTitlePanel title="Menu" style={style1}>
<div style={styles.content}>
<div style={styles.divider} />
{links}
</div>
</MaterialTitlePanel>
);
}
}
);
const styles = {
sidebar: {
width: 256,
height: '100%',
},
sidebarLink: {
display: 'block',
padding: '16px 0px',
color: '#757575',
textDecoration: 'none',
},
divider: {
margin: '8px 0',
height: 1,
backgroundColor: '#757575',
},
content: {
padding: '16px',
height: '100%',
backgroundColor: 'white',
},
};
this.props.store.hover is a observable.
The problem is that when mouse over one item, all of the items get the hover effect. What did I do wrong?
Do not set Component's props directly, set it on upper Component.
or you could use state feature, and always use setState() to change state.
write an subcomponent to control the Button State
code below maybe help
class SidebarContent extends React.Component {
constructor(props) {
super(props);
}
componentWillMount() {
this.props.store.fetchSources()
}
getArticles(src) {
this.props.store.fetchArticles(src);
}
render() {
const links = sources.map( (src,index) => <Button />);
return (
<MaterialTitlePanel title="Menu" style={style1}>
<div style={styles.content}>
<div style={styles.divider} />
{links}
</div>
</MaterialTitlePanel>
);
}
}
class Button extends React.Component {
toggleHover(){
this.setState({
hover: !this.state.hover,
});
}
render() {
const style1 = this.props.style ? {...styles.sidebar, ...this.props.style} : styles.sidebar;
const { sources } = this.props.store
const { hover } = this.state;
var linkStyle;
if (hover) {
linkStyle = {backgroundColor: 'black'}
} else {
linkStyle = {backgroundColor: 'white'}
}
return (
<a key={index} href='javascript:;' style={styles.sidebarLink} onClick={this.getArticles.bind(this, src.id)} >
<span style={linkStyle} onMouseEnter={this.toggleHover.bind(this)} onMouseLeave={this.toggleHover.bind(this)} >
<img className="ui-avaatar image" src='{ src.urlsToLogos.small }' />
<span className="side-news-item"> {src.name} </span>
</span>
</a>
);
}
}
const styles = {
sidebar: {
width: 256,
height: '100%',
},
sidebarLink: {
display: 'block',
padding: '16px 0px',
color: '#757575',
textDecoration: 'none',
},
divider: {
margin: '8px 0',
height: 1,
backgroundColor: '#757575',
},
content: {
padding: '16px',
height: '100%',
backgroundColor: 'white',
},
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Resources