React.js: Get value from an icon component works inconsistently - javascript

A table component renders trash icons that I would like to bind to mapped couponId's to post delete requests through:
<FaTrashAlt
value={record.couponId}
onClick={e => {
console.log(e.target.getAttribute('value'), `=====e.target.getAttribute('value')=====`);
}}
/>
The first row of the table shows the couponId, seen below. Clicking the above does work maybe 10% of the time, but most of the time it returns null:
Clicking the same delete icon quickly lowers the chance of the value logging so I think there is some sort of async issue in play here.
What is a more reliable way to bind a value to an icon or image and pass it to an onClick handler?

Related

React - Conditional mounting/unmounting of a component

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.

In jQuery how do I do something after an event has completed

Use case:
I have a table that users enter order lines into. The table is a list of products, they can page up and down in the table. If they've entered a quantity into one product and then page down they need to be focused on the input field in the same column they started from, but at the new row, the page down has moved to.
Problem:
The page down changes the hover location. So I can get which row has the hover state and change focus to the correct column in that row. I need code to execute after the page down has completed and a new row has: hover.
But because page down is async, getting the row with the hover state in my event handler returns the current row, not the one that will have: hover when the page down completes. How do I write a page down event handler so that code is executed after the page down has completed?
Attaching a promise to the table with code that executes after the 'keydown' type event is complete doesn't work. It runs before the new row has: hover state.
You can use document.activeElement to get the element that has focus, get the column from that and set the focus using $(columnSelector).focus() to newly populated records column.
Another way is to have focus event handler and maintain the last focused column name in a variable.

Vertical scroll in storybook is not accurate

I'm trying to implement this react-dates example, in storybook, on my code:
http://airbnb.io/react-dates/?selectedKind=DayPickerRangeController&selectedStory=vertical%20scrollable&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybook%2Factions%2Factions-panel
It looks that the info that they show about the component props that they pass are not accurate:
It, is like is copy & paste from the previous examples.
So, storybook examples, 'vertical scrollable' & 'vertical scrollable with custom month nav' are using a different func in order to load more months, it cant be 'onPrevMonthClick' & 'onNextMonthClick', that is shown on 'Show info' button.
How do I override the 'down arrow' so as to load more months or not?
Has anybody come upon that issue before?
To override the prev/next buttons completely, the only way I see how is to pass your own buttons to navPrev/navNext with your own buttons that stopPropagation when you want to stop them from activating:
navNext={
<button
onClick={e => {
const dontGoNext = true;
if (dontGoNext) {
// Stop propagation of button and prevent next month from loading
e.stopPropagation();
} else {
// do nothing..
}
}}
>
Next
</button>
}
You can checkout an example here: https://codesandbox.io/s/ry87wm8274
The reason this is the only way I see how to do it is because the navigation is tightly controlled with a click handler in DayPickerRangeController (onNextMonthClick) that handles the ability to go to the next month view.
To just disable the buttons using the DayPickerRangeController you can set minDate/maxDate which in turn disables the prev/next buttons.
Those 2 props affect the disablePrev/disableNext props (Github Lines) which are passed down through the DayPicker to the DayPickerNavigation component.
Note: These props are not available in the DateRangePicker component, because they are not passed down. Unsure as to why.
P.S. react-dates; docs aren't the best IMO. I always end up having to look at the source to understand how to do what I am wanting to do.

ReactJS onClick event which disable clicking second time on <a> tag

I'm looking a solution how to prevent to clicking and saving second time the same follower through <a> tag.
This is my code:
<a className={this.followClasses(user.following)}
onClick={this.followUser.bind(this, user.id)}
disabled={user.following}>
<i className="material-icons">person-pin</i>
</a>
onClick runs a function which save to DB a connection between current user and other user that the current user wants to follow second one and change a color from grey to grey. But when I clicked it once there is a possibility to click it twice and this way connection between a users is doubled. As I've checked there is no such attr like disable for <a> so is there any other possible solution to make unable to click it second time?
This is callback function for onClick:
followUser(userId){
UserActions.followUser(userId);
}
You can do it simply like this:
followUser(userId) {
if (!this.followUserClicked) {
this.followUserClicked = true;
UserActions.followUser(userId);
}
}
although it depends on your structure, might be better to consider storing this value in some higher level object to not loose value on view updates.
I would suggest to rather handle that in UserActions than in view.
The problem you can face with your code is that your node is probably not re-rendered after user.following changes, keep user.following value in component's state, track when changes and do this.setState({following: user.following}) after it changes, that will trigger view update.
Ok guys. Ive coped with this problem. I've added following variable to the followUser(userId, following), the same I had used to color <a> tag and it works!
followUser(userId, following){
if(!following){
UserActions.followUser(userId);
}
}

How to hide/show adf component automatically

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.

Categories