NGXS ofActionSuccessful - ngxs

I have an angular component that subscribes to ofActionSuccessful. This action is dispatched as the user clicks on a button on the page. It is possible that the user may click on this button multiple times resulting in multiple dispatch events for this action
this.actions$.pipe(ofActionSuccessful(UpdateCommunicationPreferences)).subscribe(() => {
console.log('Action Successful');
});
this.store.dispatch(
new UpdateCommunicationPreferences(this.communicationPreferenceForm.value)
);
The issue that I am running into is ofSuccessful is triggered in an accumulated manner. In other words, the first time the user clicks on the button, the "Action Successful" is printed once. Second time the user clicks on the button, it is printed twice and so forth.
Can anyone help if there is a way to not get duplicate ofSuccessful events for the past actions?
Appreciate any insight.

This package was developed with your issue in mind:
https://www.npmjs.com/package/#ngxs-labs/actions-executing
#Select(actionsExecuting([UpdateCommunicationPreference])) myActionIsExecuting$: Observable;
you can use myActionIsExecuting$ in your template with async pipe. you can also simply subscribe to myActionIsExecuting to familiarize yourself with what is returned. null will be returned when all instances of that particular action are finished.
I hope that helps!

Take a look this: https://www.ngxs.io/advanced/cancellation
Extracted from the link: "If you have an async action, you may want to cancel a previous Observable if the action has been dispatched again. This is useful for canceling previous requests like in a typeahead."
Alternatively, you can consider a pattern that disables the UI when the button is clicked (e.g. via 'in progress' dialog) before triggering the action dispatch. When the action is done processing, close the dialog.
Hope this helps.

Related

Inline Keyboard with pager that spawns more menus

I try to create following logic:
User start conversation with command /display-playlists
Bot replies with a text for first batch of playlists (or any data) from database. For example first batch is 10 rows from database. Inline keyboard that comes with this message contains buttons for each of those rows + pager button like 'next' and 'previous', for next and previous batches (i already have this implemented, the problem is in the next step)
When user clicks on a button, that is "attached" to the row, bot should reply with a message for only this row, with inline keyboard, having options, that could be applied to this row.
So user calls the conversation to show playlists, chooses one of them, then chooses action for it from bots reply.
How it looks right now
It looks the way I want it to look like. The problem is that the third step is still a part of the initial conversation, so when i click on actions (show or delete) it goes to the entry point of inner conversation, so it just duplicates the message with options.
Conversation Handler for it:
ConversationHandler(
entry_points=[CommandHandler(name, display_playlists)],
states={
0: [
ConversationHandler(
entry_points=[
CallbackQueryHandler(pager, pattern=callback_utils.is_pager_action),
CallbackQueryHandler(action)
],
states={
0: [CallbackQueryHandler(apply)]
},
per_message=True,
fallbacks=[]
),
]
},
fallbacks=[],
allow_reentry=True
)
'pager' is a method for switching through batches (returns 0), 'action' is a method that displays single row keyboard for actions (returns 0), 'apply' is what is supposed to apply chosen action, but it is not implemented yet, as i try to resolve the problem in this post.
As you can see i did put "per_message" so i hoped each message with actions to be in its own conversation, so i could choose as many playlists as i want, and then click on their actions, without then interrupting each other. My guess is that i need to somehow catch clicks on actions through a completly separate CallbackQueryHandler, but i have no idea how to implement it, as there is almost no examples on how to use "per_message" in such manner.
I know that handler right now looks scuffed, i'm just experimenting, trying to make it work, so i guess you can just ignore it.
I'm using python-telegram-bot==13.12

Vaadin item click listener double click behaviour

I am working on a vaadin application. I have provided left single click and left double click actions on a grid row via item click listner. In case of left single click it works correctly, but problem is that whenever i do left double click on grid, the listner gets invoked 3 times i.e.
Single Click
Single Click, then
Double Click
On first invoke, selected item is correct but on second and third invoke the selected item is null. Moreover sometimes there is delay in sending the click action to server(i am not getting it why). On my machine it is working correctly because client and server are both on same machine, but on actual system it looks like the request from client(browser) either reach late to server or does not reach at all.
Can anyone help me in this?
Note- Grid selection model is SingleSelection.
#Override
public void itemClick(final ItemClick<PersonData> itemClickEvent) {
final PersonData data = itemClickEvent.getItem();
if (itemClickEvent.getMouseEventDetails().isDoubleClick()) {
//some logic
} else {
//some logic
}
}
First, there's a potential bug or a limitation: the way click events work in browsers is that when you double click an element, it actually fires three events:
a single click event after the first click
a second single click event after the second click
a double click event (assuming the second click happened fast enough after the first one)
You can test this out in a plain HTML document like this:
<!DOCTYPE html>
<html>
<body>
<button ondblclick="d()" onclick="s()">Double-click here</button>
<p id="demo"></p>
<script>
function d() {
document.getElementById("demo").innerHTML += "Double";
}
function s() {
document.getElementById("demo").innerHTML += "Single";
}
</script>
</body>
</html>
You'll note that if you double-click the button, it'll print "SingleSingleDouble". So the framework's server-side events reflect the browser events in a naive way.
It would be difficult to create a server-side fix that would make the server-side events behave in a more intuitive way due to the way client-server RPC calls work in Vaadin. Here's a simplified breakdown:
If there's a server-side listener for a particular event like "click":
If there is no ongoing request, an RPC is sent to the server immediately when the event is caught in the browser. So when the first click of the double-click occurs -> boom, sent to the server
If there is an ongoing request, any client-side events that should be sent to the server are placed in a queue and the queue's events are sent to the server once the previous response has arrived
As you've noticed, the network latency may come into play here - if the request-response cycle is very fast, you might even end up making three separate requests to the server; on a slow network, it might take a noticeable delay after the first server-side listener activation before the second one does.
So: while it would seemingly make sense to deduce on the server that in the case of "single-single-double" triplet the "logical" event would be just one double-click event, what the server usually receives first is just the one single-click event, while the second click event and the double click event are possibly waiting in a queue in the browser. The server has no way of knowing that it was actually a double-click. If there's a fix to be made, it needs to be done on the client-side of the Grid implementation; I'd recommend creating a GitHub ticket about it.
Next up, as you have Grid where rows can be selected, the first click on the item selects it, the second click deselects it. Here, I'd recommend using a multi-selection grid, as there the selection is not connected to clicking a row but happens via checking a checkbox. That way, you can still have a click listener on the row and a selection that doesn't get deselected accidentally. You'll just need to make sure the previous selection is cleared when a new row is selected; this can be done in a selection listener.

Identify which button in message was clicked

I'm sending messages with Block elements(buttons) to users using Slack API (python-slackclient). Different users can get number of these and can click the buttons with a delay obviously, for example the next day.
I need to identify which button in which message was clicked.
After checking the documentation on Slack API pages it looks like action_id is the way to go as I can specify it in my request and assign it a unique value. I shall get the action_id back in response coming to my endpoint once user clicks one of the buttons which will allow me to match it with sent message.
Is this the correct way to achieve it? Are you aware any better way to implement this?
You can use an action_id on your button in order to tie your button to a response action.
So if you have several buttons that should all trigger the same action, but you'd still need to know which of those buttons was clicked, maybe you could give them all the same action_id (so you can link them to the same action), but specify unique button values.
You need to make sure your action_ids are unique, BUT you can receive a message or an action using RegEx and thus still point them all to the same handler.
For example, this action handler receives all button presses where the action_id starts with "hello"
app.action(/^hello.*/, async ({ body, ack, say }: any) => {
await ack();
await say(`<#${body.user.id}> clicked the button`);
});

Can I cancel a controller request half way in ASP MVC?

Am very new to ASP MVC
I have a list of menu options that the user can choose. Each menu selection triggers one controller as per MVC architecture .
But unfortunately some of these controllers take some time for execution to make a visible change. Because the large data needs to be binded to a grid.So all that time browser hangs(shows loading).
The worst case occurs if user selects an option which could be easily loaded, after a time consuming menu option.
Can someone help on how to dismiss one controller action request if another comes in?
Right now its the summation of all user selected actions
Eg: If user selects Menu1 and after that Menu2 . And my Menu1 controller action is taking some time to execute. By that time User clicks Menu2 which is easily loaded if clicked for first time. But since Menu2 is clicked user has to wait a long.
This is a bit old but I will attempt to answer anyway since I ran into this problem recently. If you are using MVC 5, the other requests can be cancelled for you. The trick is to use async controller actions and to add a CancellationToken parameter.
public async Task<ActionResult> MyReallySlowReport(CancellationToken cancellationToken)
{
List<ReportItem> items;
using (ApplicationDbContext context = new ApplicationDbContext())
{
items = await context.ReportItems.ToListAsync(cancellationToken);
}
return View(items);
}
When the user navigates to another page, the request is cancelled. MVC will signal to the cancellation token that the request has been cancelled. As long as you also pass the cancellation token to the async data access method like I did above, the query will be cancelled and the server will stop working on the request immediately.
I have put together a full explanation here: http://www.davepaquette.com/archive/2015/07/19/cancelling-long-running-queries-in-asp-net-mvc-and-web-api.aspx

ASP.NET MVC 3.0 - User Hammering Submit Button

Even using the Post/Redirect/Get method, and including javascript to disable a button after it has been clicked, I am having a problem with users being able to just rapidly hammer a submit button and get multiple form posts in before server side validation can stop it.
Is there any way to stop this? I've even tried this method : how to implment click-once submit button in asp.net mvc 2?
And I've tried outright blocking the UI with jquery blockUI. I have BOTH client side and server side validation in place, and they work perfectly - but a user smashing the submit button twenty times in under a second just seems to keep breaking it.
Use javascript to wire the onclick event to disable the button.
If you are already doing that and you can still get multiple form posts, then the problem is a delay between the clicking of the button and the button being disabled, and you must be submitting the form multiple times during this delay.
To fix this, make the onclick event first make a call to stopPropagation() to stop the submit event. Then validate that the form is not in submission-blocked state. You can do this by creating a page-scoped javascript variable with a boolean value like can_submit. Test for can_submit being true before submitting the form. Set the can_submit = false when the button is disabled, so even if the button is not disabled fast enough, the form will not submit if the value has already been set to false.
In most cases I'd say that this isn't worth fixing - if a user is going to do something as silly as clicking submit 20 times they should expect to get an error.
The only real fix for this is to set up your action to only accept the same form once - add a hidden field that is set to a random value when the form is loaded. When the form is posted, save that value somewhere temporarily and if it is already there you have a duplicate request that shouldn't do anything.

Resources