SunEditor In React - Validate Text Was Inputted? - reactjs

Problem
I want to validate that a user has inputted actual text into the editor, ignoring html tags and whitespace.
Details
I'm using the ReactJS SunEditor Component
I'm using Typescript
Here's an example of the content when a user doesn't type in anything:
<p><br>
</p>
and another
<p> </p>
Attempted Solutions
I've tried putting a regex in the onChange event, but it's pretty clunky and probably won't take into account all the different ways non-textual content is represented; I need a better way.
const regex = /(<([^>]+)>)/ig;
Vague Ideas
I see that the SunEditor javascript api has a utility method, onlyZeroWidthSpace that returns a boolean; it may work, but I don't see how I can access it. I'm using Typescript, so maybe there's an issue there?
Thanks for your help!

Hi I am the author of the SunEditor React Component. Please the core SunEditor instance can be accessed by attaching a ref to the SunEditor component (You can review this from the documentation). Also to get plane text (non-html text), Please use the getText method on the editor object.
Example below:
editorRef.current.editor.getText()
Notice that editorRef is the ref attached to the SunEditor Component.

Here's a funky way of doing it that seems to work. Any other suggestions are quite welcome and invited.
<SunEditor
...
onChange={content => {
const contentTestContainer = document.createElement('div');
contentTestContainer.innerHTML = content;
const textContent = contentTestContainer.textContent;
if (textContent) {
props.getFieldHelpers('description').setValue(content);
}
}}
/>

All event handler is bind the core object.
onChange
editor.onChange = (contents, core) => {
// You can use the util object
core.util.onlyZeroWidthSpace();
}

You can try this:
onBlur = {(e) => console.log(e.target.innerText)}

Related

React Select Keep Input Value After Selection

I am currently working with react-select with single selection. After selecting a particular value, I would like the user to be able to edit the typed in text (not necessarily the same as the rendered option (formatOptionLabel).
https://codesandbox.io/s/react-select-course-dfmn2?file=/src/Selector.tsx
For example, if I typed in PHYS101, and then select the option PHYS101 ... joe, and then proceed to edit the text, for backspace the form would be come PHYS10 and if I type A then it would be PHYS101A.
I attempted to use the onInputChange and onChange props, but I cannot get it to work consistently. I would appreciate any suggestions or snippets of code I could use.
There is a similar issue. Maybe that could help.
Here is a link to the issue. react-select custom tag edit feature
OR
If you wanna switch over to some other library for your specific purpose.
You could use react-selectize.
You can provide props to edit the selected option.
I solved it like this.
I pulled a reference to the internals via ref
<Select
ref={selectRef}
onChange={onOptionSelect}
/>
and in the useEffect.
useEffect(() => {
const selectObj = selectRef?.current
if (selectedOption?.value && selectObj) {
selectObj.state.inputValue = selectedOption?.value
}
}, [selectedOption])

React.forwardRef is already possible without it, so what's the use of it?

I'm confused on the point of React.forwardRef. As explained in its documentation, I understand that its main use is for a Parent Component to gain access to DOM elements of the Child Component. But I can already do that without even having to use it.
Here is a code example that you can plug into CodeSandbox and see that it works:
import React, {useRef, useEffect} from "react";
import "./styles.css";
const ChildComponent = (props) => {
useEffect( ()=> {
props.callbackFunction()
})
return(
<div ref={props.fRef}>
{"hello"}
</div>
)
}
export default function App() {
const callbackFunction = () => {
console.log("The parent is now holding the forwarded ref to the child div: ")
console.log(forwardedRef)
}
const forwardedRef = useRef(null)
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<ChildComponent name="gravy" callbackFunction={callbackFunction} fRef={forwardedRef}/>
</div>
);
}
Or here's the embed of this example. Honestly, I'm kind of new to this and I don't know exactly how embeds work and whether someone fiddling with the embed changes my original Sandbox or not, so I was hesitant to put it. But here it is.
Example Forwarding Ref
In the example, the parent App() component successfully passes a ref to the child which the child attaches to its rendered div. After it renders, it calls a callback function to the parent. The parent then does a console log where it proves that its forwarded ref now has a hold of the child's div. And this is all done without React.forwardRef.
So what then is the use for React.forwardRef?
You're absolutely right that you can do what you've described. The downside is that you're forced to expose an API (ie: the fRef prop) for it to work. Not a huge deal if you're a solo developer building an app, but it can be more problematic eg. if you're maintaining an open-source library with a public API.
In that case, consumers of the library won't have access to the internals of a component, meaning you'd have to expose it for them somehow. You could simply do what you're suggesting in your example and add a named prop. In fact, that's what libraries did before React 16.3. Not a huge deal, but you'd have to document it so people know how to use it. Ideally, you'd also want some kind of standard that everyone used so it wasn't confusing (many libraries used the innerRef naming convention), but there'd have to be some consensus around that. So all doable, but perhaps not the ideal solution.
Using forwardRef, passing a ref to a component just works as expected. The ref prop is already standardized in React, so you don't need to go look at docs to figure out how to pass the ref down or how it works. However, the approach you describe is totally fine and if it meets your needs, by all means go with that.
As mentioned in the docs , it's useful for highly reusable components, meaning components that tend to be used like regular HTML DOM elements.
This is useful for component libraries where you have lots of "leaf" components. You've probably used one like Material UI.
Example:
Let's say you're maintaining a component library.
You create a <Button/> and <Input/> component that maybe just adds some default styling.
Notice how these components literally are just like regular HTML DOM elements with extra steps.
If these components were made to be used like regular HTML DOM elements, then I expect all the props to be the same, including ref, no?
Wouldn't it be tedious if to get the button ref from your <Button/> component I'd have to get it through something like fRef or buttonRef ?
Same with your <Input/>, do I have to go to the documentation just to find out what ref to use and it's something like inputRef ? Now I have to memorize?
Getting the ref should be as simple as <Button ref={}/>
Problem
As you might know, ref will not get passed through props because, like key, it is handled differently by React.
Solution
React.forwardRef() solves this so I can use <Button ref={}/> or <Input ref={}/>.

Blur Any Focused Field onSubmit | React Final Form

This might be a bug, but I wanted to post here before I open a GitHub issue to see if the community at large has advice, or if someone can just call me out for doing it wrong.
I want to blur any focused field onSubmit. Simple.
According to the docs, the onSubmit function is passed (values, form) as arguments, and the form api includes ways to get all registered fields, and a method for supposedly bluring any field. Here's the code:
const onSubmit = async (values, form) => {
const fieldsNames = form.getRegisteredFields();
fieldsNames.forEach(name => form.blur(name));
await sleep(300);
window.alert(JSON.stringify(values, 0, 2));
};
I forked the basic example directly from FinalForms docs, and added those two lines to see if I could get their example to work, but it did not. To test, just type into the firstname field, and press your enter key. The field stays focused..
CodeSandbox Demo Here
Final Form: FormApi Docs
Thanks for reading!
form.blur() is how you tell Final Form that the field has been blurred (it marks the field's state as being blurred). It's more of a listener. To actually imperatively blur the field, you'll need a reference to the DOM element.
Something like getElementById('myField').blur().

ReactJS events - this.props.onSubmit(this.state....)

The following code snippet is from a simple Todo list which stores information on a local EOS blockchain and has a frontend web interface built on ReactJS. The question is related to ReactJS, specifically the event handler code snippet
saveTodo(e) {
e.preventDefault();
this.props.onSubmit(this.state.description)
this.setState({ description: "" })
}
The full program can be found here...https://github.com/eosasia/eos-todo/blob/master/frontend/src/index.jsx
In the body of the event handler saveTodo(e), there is a line this.props.onSubmit(this.state.description). I would like to know what exactly is going on here?
I am new to ReactJS, and it looks to that the above line of code is somehow setting a property (props) by calling a built-in function onSubmit() with an argument retrieved from the state object. Is this correct? I don’t see how onSubmit() was assigned to props anywhere in this code, but somehow we are able to use it like so: this.props.onSubmit(this.state.description) …. What’s going on here?
Thank you kindly.
P.S. pardon the terminology. I'm not sure if "event handler" or "event listener" is the right word.
The TodoForm component takes a property "onSubmit".
That line is simply calling this property (that was passed to it by its parent) and passing in the description ( taken from the state of TodoForm ).
For example:
<TodoForm onSubmit={(description) => alert(description)} />
Read more about props in react here.

Testing if something is on screen with react

I have an input field with a submit button and when someone enters something that text appears on the screen. how can I test that in react?
I know how to simulate the button click but what would the expectation be? or how would I actually be able to tell if the text is there?
You would need to use refs to check the values of input fields using React. The refs provide the hooking interface between virtual DOM element of input fields to access it values.
You scry for that input element by id or type or class. And you can access the text of that element by looking at .value
I'm not sure I understand the question... the first part of your question makes me think you want to detect when a user is typing some text in an input field, but the second part makes me think you want to automate a test, placing some text in the input and simulating click on a button, kinda confusing ...
In my last project I used that package instead of a classic input: react-contenteditable
You can hook your code to events that this component is firing:
render() {
const { selectedDbItem } = this.props
return (
<div>
<ContentEditable
onBlur={(e)=>this.onBlurField(e, 'supplier')}
className="field-value"
html={selectedDbItem ? selectedDbItem.supplier : ''}
disabled={false}
onChange={(e)=>this.onChangeField(e, 'supplier')}
onKeyDown={(e) => this.onKeyDown(e)}
/>
</div>
You can then implement the callbacks onBlur, onChange, onKeyDown (for input filtering for example ...) in the containing component.
Hope that helps

Resources