Printing in ReactJS - node.js

How do I print(printer) a DIV in my app component in react ? I have a DIV=(badgeContainer) inside which I have added a few shapes, text and Images, now i would like to print the elements inside the DIV=(badgeContainer). Is there a package which would help me do this in react ? Any help is much appreciated.

You can do this using the useRef hook and window.(open & print & close).
import React from "react";
export const Printable = () => {
const printableAreaRef = React.useRef<HTMLDivElement>(null);
const handlePrintClick = () => {
const w = window.open();
if (printableAreaRef.current?.innerHTML) {
w?.document.write(printableAreaRef.current.innerHTML);
w?.print();
}
w?.close();
};
return (
<>
<button onClick={handlePrintClick}>Click To Print</button>
<div ref={printableAreaRef}>
I want to print this
</div>
</>
);
};

There's several libraries you can use for this. I have used https://github.com/MrRio/jsPDF and it's great.

you can you this package :
ReactToPrint - Print React components in the browser
I use it and it can handle print for you

Related

how to render svg icon in nuxt 3

I am using nuxt 3 and Compositions API.
I get such a nesting, how to get rid of the extra svg tag?
I would also like to receive svg attributes whenever possible and change, for example, fill
template
<template>
<div>
<component :is="render"></component>
</div>
</template>
Script
import { h } from "vue";
const { data, pending, error, refresh } = await useFetch(svgURL);
const getDataVal = data.value
const SvgToRaw = await getDataVal.text();
const render = () => {
return h("svg", {
class: "bar",
innerHTML: SvgToRaw,
});
};
Chrome Dev Tools
I tried to create a virtual DOM tree and get an HTML element from there, not text, but I think this is a bad solution
import hv from "virtual-dom/h";
import diff from "virtual-dom/diff";
import patch from "virtual-dom/patch";
import createElement from "virtual-dom/create-element";
const betaRender = hv("span", { innerHTML: svgString });
var rootNode = createElement(betaRender);
var patches = diff(rootNode);
return patches[0].vNode.innerHTML
SSR support is important to me so I can't use standard tools

Using styled-jsx, How can I test style with enzyme?

I'm using Next.js with styled-jsx, testing enzyme + jest.
I want to test props style but I don't know How can I test.
index.js
const App = (props) => {
const { className, styles } = styles(props);
return (
<div className={`${className}`}>
<h1>test</h1>
{styles}
</div>
)
}
style.js
import css from 'styled-jsx/css';
export default (props) => css.resolve`
h1 {
color: ${props.color} || "red";
}
`
I tried to test this way but It's not working.
const wrapper = shallow(<App color={"blue"}/>);
expect(wrapper.find('h1').prop('style')).toHaveProperty('color', 'blue');
Is there way to solve this problem?
Using react-test-renderer npm package you can do snapshot testing for Style component. Try this, might help you:
import renderer from 'react-test-renderer';
test('Style component unit testing', () => {
const tree = renderer.create(<App color={"blue"} />).toJSON()
expect(tree).toMatchSnapshot()
expect(tree).toHaveStyleRule('color', 'red')
})

View collections item in Mern

I have some items in a mongodb collection, now i want to view them on a react app, i've that code, but it doesn't display nothing, but if i check value with a console.log() i get the content. How i can do?
import axios from "axios";
const viewMails = []
axios.get('http://localhost:5000/emails').then(res => {
let emailString = JSON.parse(res.request.response)
for (const [index, value] of Array(emailString).entries()) {
viewMails.push(
<div key={index}>
<h1>{value.name}</h1>
<h3>{value.email}</h3>
<p>{value.message}</p>
<p>{value.createdAt}</p>
</div>
);
}
});
export default class EmailsViewer extends Component {
render() {
return (
<div className="emails">
<h1>Sos</h1>
{viewMails}
</div>
);
}
}```
Since you are trying to do a simple component to show a list, if you're using one of the last version of React, consider using axios hook (check the package documentation to see how to add it to your project https://www.npmjs.com/package/axios-hook)
Here I show you an example of what you need to do: list demo

How to inject Material-UI stylesheets into a jest/react-testing-library test?

It seems that if you don't inject Material-UI stylesheets into a jest/react-testing-library test then jsdom will fail to get the correct styles from your components (e.g. running getComputedStyle(component) will return the incorrect styles for the component).
How you properly setup a jest/react-testing-library test so that the styles are correctly injected into the test? I've already wrapped the components in a theme provider, which works fine.
As a workaround reinserting the whole head (or the element where JSS styles are injected) before assertion seems to apply styles correctly with both getComputedStyle() and react testing library's toHaveStyle():
import React from "react";
import "#testing-library/jest-dom/extend-expect";
import { render } from "#testing-library/react";
test("test my styles", () => {
const { getByTestId } = render(
<div data-testid="wrapper">
<MyButtonStyledWithJSS/>
</div>
);
const button = getByTestId("wrapper").firstChild;
document.head.innerHTML = document.head.innerHTML;
expect(button).toHaveStyle(`border-radius: 4px;`);
});
This will still fail though when you're using dynamic styles, like:
myButton: {
padding: props => props.spacing,
...
}
That's because JSS uses CSSStyleSheet.insertRule method to inject these styles, and it won't appear as a style node in the head. One solution to this issue is to hook into the browser's insertRule method and add incoming rules to the head as style tags. To extract all this into a function:
function mockStyleInjection() {
const defaultInsertRule = window.CSSStyleSheet.prototype.insertRule;
window.CSSStyleSheet.prototype.insertRule = function (rule, index) {
const styleElement = document.createElement("style");
const textNode = document.createTextNode(rule);
styleElement.appendChild(textNode);
document.head.appendChild(styleElement);
return defaultInsertRule.bind(this)(rule, index);
};
// cleanup function, which reinserts the head and cleans up method overwrite
return function applyJSSRules() {
window.CSSStyleSheet.prototype.insertRule = defaultInsertRule;
document.head.innerHTML = document.head.innerHTML;
};
}
Example usage of this function in our previous test:
import React from "react";
import "#testing-library/jest-dom/extend-expect";
import { render } from "#testing-library/react";
test("test my styles", () => {
const applyJSSRules = mockStyleInjection();
const { getByTestId } = render(
<div data-testid="wrapper">
<MyButtonStyledWithJSS spacing="8px"/>
</div>
);
const button = getByTestId("wrapper").firstChild;
applyJSSRules();
expect(button).toHaveStyle("border-radius: 4px;");
expect(button).toHaveStyle("padding: 8px;");
});
This ultimately seems like an issue with JSS and various browser implementations like jsdom and and Blink (at least in Chrome). You can see it in Chrome when trying to modify/enable/disable these style rules (you can't).
The behavior appears to be a result of the JSS library using the CSSOM insertRule API. There's a stylesheet generated in the DOM for the styles we expect in our component, but the tag is empty - it's just used to link the shadow CSS back to the DOM. The styles are never written to the inline stylesheet in the DOM, and as a result, the getComputedStyle method does not return the expected results.
There's an open issue to address this behavior and make development easier.
I switched my custom components to styled-components, which does not have some of these idiosyncrasies.
Material-UI is planning on transitioning soon as well.
You could add this to a custom render function. After rendering, the function pulls the styles out of cssom and puts them into a style tag. Here is an implementation:
let customRender = (ui, options) => {
let renderResult = render(ui, options);
let styleElement = document.createElement("style");
let styleText = "";
for (let styleSheet of document.styleSheets) {
for (let rule of styleSheet.cssRules) {
styleText += rule.cssText + "\n";
}
}
styleElement.textContent = styleText.slice(0, -1);
document.head.appendChild(styleElement);
// remove old style elements
let emptyStyleElements = document.head.querySelectorAll('style[data-jss=""]');
for (let element of emptyStyleElements) {
element.remove();
}
return renderResult;
}
I can't speak specifically to Material-UI stylesheets, but you can inject a stylesheet into rendered component:
import {render} from '#testing-library/react';
import fs from 'fs';
import path from 'path';
const stylesheetFile = fs.reactFileSync(path.resolve(__dirname, '../path-to-stylesheet'), 'utf-8');
const styleTag = document.createElement('style');
styleTag.type = 'text/css';
styleTag.innerHTML = stylesheetFile;
const rendered = render(<MyComponent>);
rendered.append(style);
You don't necessarily have to read from a file, you can use whatever text you want.

Is it possible to capitalize first letter of text/string in react native? How to do it?

I have to capitalize first letter of text that i want to display. I searched for it but i cant found clear thing to do that, also there is no such props for text in react native official documentation.
I am showing my text with following format:
<Text style={styles.title}>{item.item.title}</Text>
or
<Text style={styles.title}>{this.state.title}</Text>
How can I do it?
Suggestions are welcome?
Write a function like this
Capitalize(str){
return str.charAt(0).toUpperCase() + str.slice(1);
}
then call it from <Text> tag By passing text as parameter
<Text>{this.Capitalize(this.state.title)} </Text>
You can also use the text-transform css property in style:
<Text style={{textTransform: 'capitalize'}}>{this.state.title}</Text>
React native now lets you make text uppercase directly with textTransform: 'capitalize'. No function necessary.
import React from 'react'
import { StyleSheet, Text } from 'react-native'
// will render as Hello!
export const Caps = () => <Text style={styles.title}>hello!</Text>
const styles = StyleSheet.create({
title: {
textTransform: 'capitalize'
}
})
Instead of using a function, a cleaner way is to write this as a common component.
import React from 'react';
import { View, Text } from 'react-native';
const CapitalizedText = (props) => {
let text = props.children.slice(0,1).toUpperCase() + props.children.slice(1, props.children.length);
return (
<View>
<Text {...props}>{text}</Text>
</View>
);
};
export default CapitalizedText;
Wherever you're using <Text>, replace it with <CapitalizedText>
just use javascript.
text.slice(0,1).toUpperCase() + text.slice(1, text.length)
TextInput have this to handle using
autoCapitalize enum('none', 'sentences', 'words', 'characters')
for example try like this
<TextInput
placeholder=""
placeholderTextColor='rgba(28,53,63, 1)'
autoCapitalize = 'none'
value ='test'
/>
this worked for me!
labelStyle:{
textTransform: 'capitalize',
fontSize:20,
},
Since this is very general functionality I put it in a file called strings.js under my library:
// lib/strings.js
export const CapitalizeFirstLetter = (str) => {
return str.length ? str.charAt(0).toUpperCase() + str.slice(1) : str
}
And simply import it in the components that need it:
import React from 'react';
import { View, Text } from 'react-native';
import { CapitalizeFirstLetter} from 'lib/strings'
export default function ComponentWithCapitalizedText() {
return <Text>CapitalizeFirstLetter("capitalize this please")</Text>
}
I just added a prototype function, based on #mayuresh answer
String.prototype.Capitalize = function() {
return this.charAt(0).toUpperCase() + this.slice(1);
}
and use it like this:
myStr.Capitalize()
If you want to capitalize only the first letter of the input:
function CapitalizeFirstLetterOfInput () {
const onInputUppercase = (e) => {
let firstLetter = e.target.value.charAt(0);
e.target.value = firstLetter.toUpperCase() + e.target.value.slice(1);
};
return (
<div>
<input onInput={onInputUppercase}/>
</div>
)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
if anyone interested doing it by just css/style
<strong style={{textTransform: 'capitalize'}}>{props.alert.type}!
here inner {} is for object {textTransform: 'capitalize'}
This answer worked for me:
text.slice(0,1).toUpperCase() + text.slice(1, text.length)
I used it with a props in an alt tag:
`${(props.image).slice(0,1).toUpperCase() + (props.image).slice(1, (props.image).length)}`
Then I guess you can apply that to any text you want.

Resources