Framer / React: Can't change focus state of Text Input onClick / onChangePage - reactjs

This is a Framer/React question:
I have a bunch of text fields in a "page" component and I want the focus to shift on every "page" change.
There's a button controlling the pager but no trigger (onPageChange / onClick) is changing the attribute of "focus" on the relevant text input.
This is the code I tried using to change the value of foc2 (the focus attribute) to true
When I manually change it to true it works, but in this case it doesn't
export function Page(): Override {
return {
currentPage: state.page,
onChangePage: (index) => {
state.page = index
state.foc2 = true
},
}
}

Do you have more complete code you could share?
Make sure you set the state to the index of the current focused input, and use that to change the currentPage property.
Happy to help if you send more context, you can also find more help in Framer's community at https://framer.com/r/discord

Related

IntersectionObserver Flickering with ScrollIntoView

I'm trying to build a custom input that you can change its value by scrolling with IntersectionObserver and ScrollIntoView
The problem that I'm facing is that when I try to make the component controlled with a state it starts to flicker when scrolling.
I have the example here in this sandbox, and you can see the input gets initialized correctly with the correct value, but when you try to change it.. there is a flickering at the beginning of the scroll event. also resetting the input by the button does seem to work correctly.
I'm not really able to figure out how to get the updates correctly done in each event since I'm very new to Intersection observer
Try setting the threshold value to 1 such that it will fire only when it goes out of boundary completely.
const observer = new IntersectionObserver(
(entries) => {
const selectedEntry = entries.find(
(e) => Number.parseFloat(e.target.textContent) === value
);
selectedEntry?.target?.scrollIntoView();
entries.forEach((entry) => {
if (!entry.isIntersecting) {
return;
}
!isFirstRender &&
onChange(Number.parseFloat(entry.target.textContent));
});
},
{ threshold: 1 } // changed to 1
);
Also please do as the linter says, and add proper dependencies for the useEffect hook unless when not needed.
If you are using React, you might consider react-intersection-observer.
In my case, I was able to remove flickering by setting option triggerOnce: true.

How to trigger onchange only when the content changes in draft js editor?

The onchange method in draft js is executed by the Editor when edits and selection changes occur. But I want to call trigger onchange only when the user is writing or the content changes and not on focus or selection. Is there any way I can compare the previous and current editor state?
You cannot do exactly that because draft-js keep selection state of your mouse inside the editor state, onChange must be triggered, and you must update the editor state, but you check for the old and new editor state plain text and know for sure if some characters are added or deleted
const [editorState,setEditorState]= useState(EditorState.createEmpty());
function onChange(newEditorState: EditorState) {
const currentPlainText = editorState.getCurrentContent().getPlainText();
const newPlainText = newEditorState.getCurrentContent().getPlainText();
setEditorState(newEditorState);
if (currentPlainText.trim() !== newPlainText.trim()) {
/**
* do what you want knowing that you have different content in the editor
*/
}
}
I use undoStack.size property to detect the content change. It works great.
https://draftjs.org/docs/api-reference-editor-state/#undostack
onEditorStateChange = (editorState) => {
const changed = !!editorState.getUndoStack().size
...
}

With ReactJS Popup, how can I make it only show one pop up at a time?

I am experimenting with different React popup libraries. I found reactjs-popup and began playing with the codesandbox. I created a fork of the environment here https://codesandbox.io/s/pp60zjkxlj
When I click the first (or second) button, it displays the corresponding popup. What i'd like is so that when I click other button, it will display that button's popup and hide any other popups that are visible. The goal is that only one popup should be visible on screen at any time.
Is this possible with this library?
See https://codesandbox.io/s/pp60zjkxlj
have a common state for popup when first button is clicked set the state to first button and based on the state
I would look into Portals where you can use a portal that sits outside of the jsx that wishes to use it.
imo it is the best way to implement a modal and i believe there's not to much need to add another dependency to your project and just create one this way that matches your needs.
You will need to pass props into the Popup to tell it when to open and when not to open.
Your component should have state set for each popover or be passed in props to tell the Popovers when to display. You can set in a constructor a default state and spread those before setting the new state with the new Popover open. This is how I handle modals.
constructor(props) {
super(props);
this.state = {
vendor: {} // Just showing my default state this gets set and this.defaultState is spread after my fetch request completes in componentWillMount()
};
this.defaultState = {
isPopoverOpen: {
// ---- Default Popover booleans can go here
editVendor: false
}
};
}
Actual function that controls the Popover status in the state.
// onClick of element would be onClick={this.handleTogglePopover('editVendor')}
handleTogglePopover = id => {
const currentState = Object.assign({}, this.state);
this.setState({
currentState,
...this.defaultState, // spreading default will set everything to false
isPopoverOpen: {
[id]: true // then the newly clicked to true
}
});
};

How to prevent row selection after clicking on link inside custom rendered cell in AgGrid

I am using AgGrid and have rowSelection="multiple" on my grid, have {cellRendererFramework: PrintCell} on the last column, which is a small component that displays a link.
I want it so, when I click on the link inside PrintCell, a certain action should be executed, without altering the the state of the grid itself, and keep the current selected lines selected without making the row containing the link selected. I tried doing event.stopPropagation and event.preventDefault to prevent the parent row from getting selected, to no avail.
Any Idea how to achieve this ? thanks
Updated for June 2018:
The API for Ag-Grid has changed. The key change is that there needs to be a change to e.api.gridOptionsWrapper.gridOptions.suppressRowClickSelection from within the onCellFocused event of the grid
Here is a full solution that uses a reusable cell renderer to create actions or buttons at the end of a row that won't trigger row selection. This solution assumes that you are using the React version of ag-grid and that you are using a custom cell renderer.
// class fields
disableClickSelectionRenderers = ['rowActionRenderer'];
// columns defs
...
{headerName: '', field: 'someButton',
suppressMenu: true, suppressFilter: true, suppressSorting: true,
suppressMovable: true,
suppressNavigable: true, suppressResize: true,
cellRenderer: 'rowActionRenderer',
cellRendererParams: {
icon: <i className="fa fa-pencil"/>,
onClick: (e, props) => {
// do the action
},
},
},
render() {
<AgGridReact
columnDefs={...}
// ... other properties
onCellFocused={e => {
if (e.column && this.disableClickSelectionRenderers.includes(e.column.colDef.cellRenderer)) {
e.api.gridOptionsWrapper.gridOptions.suppressRowClickSelection = true;
}
else {
e.api.gridOptionsWrapper.gridOptions.suppressRowClickSelection = false;
}
}}
}
Since the row click is a specified behaviour it might be easier to perhaps use the checkbox selection and disable the focus row selection entirely. But if you want to keep with this path I generated the required behaviour by intercepting the event in the cell Focus and blocking row selection there.
private onCellFocused($event) {
if($event.column && $event.column.colId == "commentid"){
this.gridOptions.suppressRowClickSelection = true;
} else {
this.gridOptions.suppressRowClickSelection = false;
}
This switches the row selection event of entirely but only if you select the column where you don't want the behaviour to occur (caveats: angular 2 example and we have wrapped the ag-grid inside our own component.
Hope this helps...
For TS + Angular
use it inside your rowclick method
Incase if you want to ignore a particular cell this piece of code can help you
if (!(
this.gridApi?.getFocusedCell()?.column.getColId() ===
'columnName')) {
//your code here
}
the gridApi can probably be got from the onGridReady method

Manually update DraftJs ContentState with clicked text

How can I manually update DraftJs's ContentState in response to clicked text?
I have a list of text item. When one is clicked I am passing that text down to Draftjs, but because I am setting the state using componentWillReceiveProps() it requires that I click the text twice to get an update.
componentWillReceiveProps() {
const activeNoteText = this.props.activeNoteText;
if (activeNoteText !== '') {
this.setState({ editorState: EditorState.createWithContent(ContentState.createFromText(activeNoteText)) });
}
}
First click: Update the App state and pass props down to Draftjs (component updates before receiving new props)
Second click: Now the prop is properly set and Draftjs updates (component updates with the props received on the first click)
How can I accomplish this in one pass? I know there's no componentDidReceiveProps and I know there's a good reason, though I can't claim to fully understand yet, so what's the best practices way to accomplish something like this?
Why are you using componentwillReceiveProps?.
What you can do, is have the states your setting in Draftjs i.e. editorState(Well, that's what I can make out) in its parent and whenever a list item is clicked on the click handler for that update the editorState and then pass it as props to Draft js.
Further for the condition, where you are checking if it is not empty,
You could use the
getInitialState(){
.....
}
For initialization when your component is initially loaded. So you could have a default value for editorState.

Resources