There is an UI I have created using React. There are two text fields to enter value, after entering and saving those values will be populated in a table below the two fields(we are using antd for designing).
However when I click a single record in the table and click edit in that particular record data from that record will be populated to the above mentioned text fields. When this happens I want my app to scroll up and show those two text fields which are ready to be edited.
But currently it stays at the same position after clicked edit, without scrolling up and showing two text fields. Here's an image descripting my experience
Check this answer to find how to control srollTop: https://stackoverflow.com/a/55184755/2360631
But I don't think it's a good idea, maybe you can consider to freeze the edit area otherwise when you finish edit you may need to scroll back again...
Basically you want to set focus to some component after a re-render.
To refer to a particular component, use react refs
make a react ref of whatever you want to set focus to and assign it as a ref prop
constructor() {
super();
this.foo = React.createRef();
}
componentDidUpdate() {
this.foo.current.focus();
}
<Bar ref={this.foo}> .... </Bar>
foo is the name of ref
Bar is the component you want to set focus to
in your case it can be a parent of both input fields or any one of the input fields
Related
Currently, I am using Select component as a column in Ant Design table like that:
enter image description here
But I found that although the record has changed, the value shown in "Select" component still is not changed. That means when I change to page 2 or 3, the "Action" column, or what shown in "Select" component in particular, still displays the same values, even thought the record is changed.
enter image description here
When I click on to change the value, "Select" works normally & call the API to update the correct record. I have tried to use "shouldCellUpdate" attribute of "Table" component but it didn't work.
Could you please help me solve this problem or give me a suggestion?
Thank you.
I have a form that is dynamic and display inputs (select, multiple or text) when an answer is provided on previous question.
When a text input is created, it is because of the answer of the previous question, which means that many way can be created by answering differently.
The problem :
When I answer a select question, for example, a text input can be displayed next. If I answer this input, another input can be displayed. But, if I update my answer for the first select input, this means that a new way is created, but the next one is still a text input, so ReactJS don't create a new one, just update the existing one. The fact is that the value is still in the input, and that's not what I want, I need the value to be updated, either by a defined value, or by an empty one, but this need to be updated.
I have created a stackblitz example with a little reproduction.
In this reproduction, you can choose a value in the select input, but then if you choose the other one, the value will not be updated on the input. The only way to update it, is to clear it and recreate it by choosing a new value.
I know that in this example, using the value from the state and updating the state directly in the change method will work, but in my project I don't have a defined number of text inputs.
The only thing I see to do it with state, is to create an array and dynamically adding or removing values when inputs are added or removed from the form. But I would prefer a "refresh" input method.
You can add your selected values inside Array state then loop map the
//states
this.state = {
values: []
};
//joinin new values with previous array
handleSelect(event) {
var joined = this.state.values.concat(event.target.value);
this.setState({ values: joined });
}
//then mapping on render
<div>
{
this.state.values.map(x=>(
<Input value={x} placeholder="type here" />
))
}
</div>
Here is working example in your code:https://stackblitz.com/edit/react-n1jbk6
Context
Let's say I have page that displays a list of employees, along with many other buttons and components. and whenever I click on an employee, a side panel appears with a bunch of information about that employee. If I click on any other employee while an employee is selected, the side panel remains intact with only the information inside it being re-fetched and updated.
I can also, change the employee's information from that side panel by editing the different fields and clicking Update which bulk updates every updated fields.
Problem Statement
Whenever an employee's information is being edited, I can also click on another employee, which, of course, means that the edited data for the previous employee is lost.
Objective
What I need to do in this case is that, whenever an employee's information is being edited from the side panel (a flag is present to denote that), and if any other component/buttons apart from Update is clicked, then I need to show a modal which states that everything that is unsaved would be lost. If the user selects Ok, the component that was clicked should mount/rendered/perform whatever it does. Otherwise, the user should go back to the previous state.
I initially tried to achieve that by using componentWillUnmount of the sidepanel, but it didn't really work because that component will unmount anyway. What I am thinking is that, I need to put a onClick handler in every button/component now apart from that 'Update' which checks if any information is being edited, if yes it will render that component, if not it will render that modal, and the user decides what to do in that modal. I am very skeptic about this as well by placing checks everywhere for a minor thing.
Anyone with experience about related to this use case ? Any insights would be highly appreciated. :)
First Put isEdited state isEdited: false Then when you edit the post then set isEdited to true. When user clicks update then set isEdited back to false. When user clicks button other than update then check isEdited if isEdited is true then dispay modal with message and button when button of model is click set isEdited to false.
Hopefully this will help
There are a few ways I can think to do this.
Add a check at the start of the function for each buttons onClick. As you've mentioned already, this is tedious, especially if there are lots of buttons that should affect the state.
Create a function that wraps the onClick functions, to perform this check. Similar to 1, however a bit easier to repeat:
const myOnClick = newEmployeeNumber => {
myState.employeeToView = newEmployeeNumber;
}
const checkUserWantsToContinue = (onClickToRunWhenContinued) => {
if (myAppState.isEdited) {
promptUserToSaveFirst();
} else {
onClickToRunWhenContinued();
}
}
return (
<div onClick={checkUserWantsToContinue(myOnClick)} />
);
You mentioned that you are trying to put this into the componentWillUnmount function. That implies that something is making the component unmount. Can you add the check in there? So rather than checking with the user before the component unmounts, check with them before the action that makes the component unmount.
All the examples I have found that keep local state can't provide an initial value for the input. In my case a parent component retrieves field from a server and passes these to my input form where the fields shall be editable. But I don't want to pass each change back up the hierarchy if I can avoid it, rather only when the form is submitted (either via button or by pressing enter)
Update: the usage is as follows. Imagine a todo list. The top level holds the list and the detail component. When I click at the list the detail should update to show the selected todo text. That text should be editable.
So as far the the detail component goes the initial state of the input is the text from the list that gets passed down in props. It needs to change when a different todo in the list is selected. On the other hand I should be able to edit it and when submit triggered that todo text should be passed back up via a callback prop.
So I have to keep local state to collect the input, but I want that state to be initialized with the existing todo text from the list. If I use the Facebook example of an uncontrolled form, I find the edited text remains displayed when I switch to a different todo in the list. Maybe I'm doing it wrong or is it a conceptual problem? Using controlled input initializing the state in the constructor doesn't work either because the constructor only gets called once (not on each re-render)!
I solved the problem by using the lifecycle method componentWillReceiveProps(nextprops) where I can set the state to the new props. This method gets called each time a re-render becomes necessary - in my case because the parent changes the childs props.
See https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops
You can set the initial state based on the property passed in from the parent, then edit that state in the component before submitting with the form submission
Hi I want to hide an adf component automatically.I have a selectOneChoice that contain some number (from 1 to 12).
Example when I select 2, it show's two field automatically without clicking any button..
i used this function to hide a declared componenet but just when i click a button..
function enableField(actionEvent) {
var nameInputText = actionEvent.getSource().findComponent("soc1");
nameInputText.setProperty("visible", true);
actionEvent.cancel();
}
i set the componement "soc1" visible = true than through the javascript function i change it..
SO the probleme here is how to read the number from the selectonechoise and how to set the component visible directly without clicking any button.
Actually Rendered won't do what you want. You want to use Visible property instead. Rendered causes the actual markup for the component not to be rendered on the page, so a Partial Refresh will not cause it to appear. Rendered is reserved, usually, to hide items that are secure. We set rendered property to false on the item(s), but then refresh the parent containing component - usually a layout manager - then it works. So either refresh the layout manager that contains the item or use Visible. I demonstrated this exact use case last week in class and it works as described.
Basicaly, you don't need javascript solution or any programming to achieve this.
You should set attributes rendered(this way component won't be rendered at the page at all) and partialTriggers that points to selectOneChoice component for components you want to show or hide. Also you have to set autoSubmit="true" for your selectOneChoice component.
<af:selectOneChoice id="soc1" autoSubmit="true" .../>
<af:panelGroupLayout id="plg1" partialTriggers="soc1">
<af:outputText id="ot1" rendered="#{bindings.lov.inputValue le 1}" inputValue="text1"/>
</af:panelGroupLayout>
Note: its not working code, just a sample
It will work following way, on valueChange event at selectOneChoice component value is submitted and partialRefresh fires for components that have it in partialTriggers specified. And rendered attribute will either render or remove component depending on it's EL expression. Components that should be managed wrapped into another component to make sure PPR reach it when they ain't rendered.