Confirm box is blocking/pausing - angularjs

I have a ng-click="myFunc(aEntry)"
And then myFunc is this:
MODULE.myFunc = function(aEntry) {
aEntry.hilite = true;
if (!confirm('Are you sure?')) {
aEntry.hilite = false;
return;
}
};
However it wont update the dom to show it highlighted. The confirm box seems to be pausing it. Does anyone know a work around?

It is because confirm is a blocking function. I understand you want to have a ui change, but
aEntry.hilite = true;
is not a UI change. It is a logical change. You probably have an event handler which runs after you have called confirm. You need to guarantee that the highlighting ui operation is performed before you call the confirm. There are several ways to do it.
The most primitive way is to use setTimeout and put your confirm call inside it, using a time, which is surely longer than the time you need to wait for the ui handler to be executed.
A slightly better approach is to use setInterval until the ui change has occured.
But the best approach would be to pass the confirm with a function wrapped around it used as a callback for the ui change or to trigger the ui change event before you call confirm.

Related

How to create my own onChangeComplete function for input type color on React

With react-color https://casesandberg.github.io/react-color/ .
I can use ready-made onChangeComplete function from react-color.
But I wonder how can I create that onChangeComplete by using input type color tag.
I tried onBlur but the color won't change until user clicks or presses tab
On the other hand, using onChange keep firing updates.
Because currently I'm using redux state, so dispatching update continuously when I drag and choose color isn't a good way.
Any ideas how to create onChangeComplete?
It depends on how you'd like to define a change. To prevent continuous updates every time the mouse moves, you'll probably want to update Redux state only when the mouse stops moving. (This seems to be the behaviour on the page you linked to).
You could use the following JavaScript to detect when the mouse stops moving:
let timer;
window.addEventListener('mousemove', function (e) {
console.log('Mouse moving');
clearTimeout(timer);
timer = setTimeout(() => console.log('Mouse stopped'), 300);
});
Then, try putting the above code inside your ComponentDidMount() method and replace console.log('Mouse stopped') with whatever Redux action you want to dispatch!
300 is the number of milliseconds without movement that will trigger the action, which could be changed depending on how sensitive you want your app to feel.
Lastly, remember to remove the event listener in your ComponentWillUnmount() method.
https://github.com/casesandberg/react-color/blob/7ee60d845e5d5e11e4f6ecb895b2d9755c59d09d/src/components/common/ColorWrap.js#L30
Here is the code that how react-color implemented onChangeComplete.
It is hard coded using debounce.
I put the link there for anyone interested in using that solution

Trying to trigger a WheelEvent programmatically with Hammerjs

I am using a library (https://github.com/asmyshlyaev177/react-horizontal-scrolling-menu) that scrolls on use of the mousewheel, and I want to use this functionality when swiping left or right.
I am using hammerjs to replicate swipeleft and swiperight behavior, and this is working.
However, creating a WheelEvent does not seem to trigger the functionality dependent on the WheelEvent.
I am using componentDidUpdate for now as my react lifecycle method because for some reason this.containerRef.current is always null in componentDidMount, but once I figure out the reason behind that, I'll probably move it.
Anyway, here's my code:
componentDidUpdate() {
if(this.containerRef.current !== null) {
this.hammer = Hammer(this.containerRef.current)
this.hammer.on('swiperight', () => alert("swipe right"));
var wheelevent = new WheelEvent("wheel", {deltaX: 500, deltaY: 500});
this.hammer.on('swiperight', () => window.dispatchEvent(wheelevent));
}
}
Now I want to point out, the alert for swipe right DOES happen, so the behavior is definitely triggering, however my WheelEvent is not being caught by the scroll library.
How should I trigger a WheelEvent programmatically?
EDIT - I made a codepen about it:
https://codesandbox.io/s/react-horizontal-scrolling-menu-fi7tv
My hunch is that issue is related to Dragging being disabled and the event is canceled.
So you need to send the event down the chain a bit. I have updated the codesandbox below which works
https://codesandbox.io/s/react-horizontal-scrolling-menu-j46l8
The updated code part is below
var elem = document.getElementsByClassName("menu-wrapper")[0];
this.hammer.on("swiperight", () => elem.dispatchEvent(wheeleventRight));
this.hammer.on("swipeleft", () => elem.dispatchEvent(wheeleventLeft));
You may want to better the approach though in a more reactive fashion later. But this does show that once you sent the event in lower order elements the wheeling does work well

React - Old promise overwrites new result

I have a problem and I'm pretty sure I'm not the only one who ever had it... Although I tried to find a solution, I didin't really find something that fits my purpose.
I won't post much code, since its not really a code problem, but more a logic problem.
Imagine I have the following hook:
useEffect(() => {
fetchFromApi(props.match.params.id);
}, [props.match.params.id]);
Imagine the result of fetchFromApi is displayed in a simple table in the UI.
Now lets say the user clicks on an entity in the navigation, so the ID prop in the browser URL changes and the effect triggers, leading to an API call. Lets say the call with this specific ID takes 5 seconds.
During this 5 seconds, the user again clicks on an element in the navigation, so the hook triggers again. This time, the API call only takes 0,1 seconds. The result is immediatly displayed.
But the first call is still running. Once its finished, it overwrites the current result, what leads to wrong data being displayed in the wrong navigation section.
Is there a easy way to solve this? I know I can't cancel promises by default, but I also know that there are ways to achieve it...
Also, it could be possible that fetchFromApi is not a single API call, but instead multiple calls to multiple endpoints, so the whole thing could become really tricky...
Thanks for any help.
The solution to this is extremely simple, you just have to determine whether the response that you got was from the latest API call or not and only then except it. You can do it by storing a triggerTime in ref. If the API call has been triggered another time, the ref will store a different value, however the closure variable will hold the same previously set value and it mean that another API call has been triggered after this and so we don't need to accept the current result.
const timer = useRef(null);
useEffect(() => {
fetchFromApi(props.match.params.id, timer);
}, [props.match.params.id]);
function fetchFromApi(id, timer) {
timer.current = Date.now();
const triggerTime = timer.current;
fetch('path').then(() => {
if(timer.current == triggerTime) {
// process result here
// accept response and update state
}
})
}
Other ways to handle such scenarios to the cancel the previously pending API requests. IF you use Axios it provides you with cancelToken that you can use, and similarly you can cancel XMLHttpRequests too.

How to differentiate between browser back button and $state.go (dynamic params)?

I need to simply update the URL params in some cases (through code) and not trigger any events. But, I still need to trigger certain actions if the user goes back using the browser back button or if he changes the url params manually.
Prior to UI-Router v1.x, I used to use { notify: false } in combination with the $stateChangeSuccess event for this kind of stuff. But now that the dynamic params are the way to go I can't figure out how to make this work any more.
I have defined all the params of the route as dynamic, and when I execute the $state.go(".", params), the controller does not get refreshed. Which is expected. The $transition.onSuccess does however still fire which I find slightly odd and I don't expect this event to fire in this case.
When I move back with the back button, or if I change a param manually, the same thing happens. The controller doesn't get refreshed and the $transition.onSuccess fires.
My main problem is how do I know one event came from the user, and the other one came from the code? What am I missing here? I checked out the transition param of the onSuccess callback, but couldn't find anything on it that would help me. Is there a different event/hook I should use or is this simply not possible any more with the latest UI-Router?
Thnx.
Seems like I found a way to find out where the transition came from. If somebody has a different/better solution, please post it, I don't find this the neatest solution ever but it works and considering I couldn't find a better one, I'll stick with it until someone shows me a better way.
// The "to:" ensures the event doesn't trigger for other routes
this.$transitions.onSuccess({ to: "your.route" }, (trans) => {
let changedParams = trans._changedParams();
if (trans._options.source === "url" && // transition came from URL change
changedParams && changedParams.length > 0) { // at least one param changed
// do something
}
});

Store update doesnot reflect

I am following React & Redux. I have actions, reducers working separately. I am managing state more or less properly.
I am trying to create a ui which is having few textboxes and a button(disabled). In text boxes i had added onchange event on which it call a function
onChangeTextbox(){
}
In this function I do the following thing.
1. I update the state of the redux store.
onChangeTextbox(){
updateStateOfTextBox();
}
2.After doing this I look for whether all the text boxes, in the ui, is having something in it. If so I will enable my button to do further operations.
onChangeTextbox(){
updateStateOfTextBox();
updateStateOfButton();
}
Everything is working good except the one thing.
That one thing is as soon as I give the last empty textbox one character, the button is not enabled immediately, and when I give more character the button gets enabled. Similarly vice versa for disabling button.
The problem which I found is that when control complete its job of function updateStateOfTextBox(); and enters the updateStateOfButton(); function the state remains same. And again when render() occurs the change in state is reflected then.
I want to fix that issue and I am not getting any way out. Any solution and suggestion to this will be appreciated.
Thanks.
I found the solution to such situation.
componentsWillRecieveProps(newProps){
}
this method of the life cycle changes the game.
componentsWillRecieveProps(newProps){
newProps.state // this will give you new updated state which your action updated.
this.props.state // this will give you local or your state
// Here you can update your local state with global state
// And call the other function here as
updateStateOfButton();
}
Therefore the solution can be interpreted like
onChangeTextbox(){
updateStateOfTextBox();
}
componentsWillRecieveProps(newProps){
.
.
updateStateOfButton();
}

Resources