How to create custom event for updating Query state? - events

I am trying to create a custom event for Query to reload and refresh the query state when the event happens.
I need a custom event similar to Spartacus' OrderPlacedEvent. My custom event actually works, but the time when
HTTP call for reloading query state is triggered is not right. Instead of firing an HTTP call when I visit the quotes page,
it happens immediately when the event is dispatched on the second step during the checkout process.
Creating event class QuotePlacedEvent:
export abstract class QuoteEvent extends CxEvent {
userId?: string;
activeCartId?: string;
}
export class QuotePlacedEvent extends QuoteEvent {
static readonly type = 'QuotePlacedEvent';
quote: any;
}
Dispatching the event during the checkout process when a quote is created for example on the second step:
this.eventService.dispatch(
{
userId: payload.userId,
activeCartId: payload.cartId,
quote: cart,
},
QuotePlacedEvent);
Quote query called when Quotes page is visited:
protected quotesQuery: Query<any> = this.query.create(() =>
this.userIdService
.getUserId()
.pipe(switchMap(userId => this.quoteConnector.getQuotes(userId))),
{
reloadOn: [LanguageSetEvent, QuotePlacedEvent],
resetOn: [LogoutEvent, LoginEvent],
}
);
getQuotesAndApplication(): Observable<any> {
return this.quotesQuery.get();
}
I saw method in ProfileTagPushEventsService orderConfirmationPageVisited() which listens to OrderPlacedEvent. Do I need that implementation too:
/**
* Listens to QuotePlacedEvent events
*
* #returns observable emitting events that describe order confirmation page visits in a profiltag compliant way
* #see QuotePlacedEvent
* #see QuoteConfirmationPushEvent
*/
quoteConfirmationPageVisited(): Observable<ProfileTagPushEvent> {
return this.eventService
.get(QuotePlacedEvent)
.pipe(map(item => new QuoteConfirmationPushEvent(item)));
}
I wanted to add my custom event by calling the method addPushEvent from ProfileTagPushEventsService, but I can't import it, since it is not exported.
Any idea what am I missing and why the custom event doesn't behave in an expected way?

The query is always "listening" for the events you tell it to listen to, and if you fire the event in the 2nd checkout step, query will react to it. This is by design.
If you need the query to react to an event which happens when you visit the quotes page, you can try to create the QuotesPageEvent, make the query listen to it, and dispatch it once the user actually navigates to the quotes page. You can see an example of a page event here.
Maybe one improvement you can do, is to make sure the that quotes have been placed before dispatching the page event. For this, you can use the power of rxjs to listen to your QuotePlacedEvent and the page visited event, and fire a final event. The quire should be listening to this final event.

Related

NGXS State documentation

I'm new to NGXS and I'm trying to fully understand the docs so I can start using it knowing what I'm doing.
There is one thing I don't understand in this code snippet from here.
export class ZooState {
constructor(private animalService: AnimalService) {}
#Action(FeedAnimals)
feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
return this.animalService.feed(action.animalsToFeed).pipe(tap((animalsToFeedResult) => {
const state = ctx.getState();
ctx.setState({
...state,
feedAnimals: [
...state.feedAnimals,
animalsToFeedResult,
]
});
}));
}
}
Just below this code, it says:
You might notice I returned the Observable and just did a tap. If we
return the Observable, the framework will automatically subscribe to
it for us, so we don't have to deal with that ourselves. Additionally,
if we want the stores dispatch function to be able to complete only
once the operation is completed, we need to return that so it knows
that.
The framework will subscribe to this.animalService.feed, but why?
The action, FeedAnimals, uses the injected service, AnimalService to feed the animals passed in the action's payload. Presumably the service is operates asynchronously and returns an Observable. The value of that Observable is accessed via the tap function and is used to update the ZooState state context based on completing successfully.
In order to use NGXS specifically and Angular in general, you really have to understand RxJS... here's my goto doc page for it

How To Get Data From A Custom Event In Magento

I have an observer module that I have written for Magento. It simply monitors an event called mgd_order_prep which is triggered by a custom dispatcher like this:
Mage::dispatchEvent("mgd_order_prep", array('orderdata' => $order));
$order is simply a magento sales/order object.
My event fires and my function in the proper class executes:
function updateOrderPrepPDF($observer)
{
Mage::log("Update Order Prep",null,'orderprep.log');
Mage::log($observer->getOrderdata(),null,'orderprep.log');
}
I see what I should after the first log event, but I dont see ANYTHING for when I try to output the order data (it outputs blank - or null).
How do I get the data I pass in at the dispatch event out at the execution point?
You can directly get Data using getData() method :
function updateOrderPrepPDF($observer)
{
Mage::log(print_r($observer->getData(),true),null,'orderprep.log');
}
Check this log inside var/log directory.
Try this code and let me know if you still have any query.

Yii2 session event before close/destroy

I want to run some code every time before user session is being destroyed for any reason. I haven't found any events binded to session in official documentation. Has anyone found a workaround about this?
There are no events out of the box for Session component.
You can solve this problem with overriding core yii\web\Session component.
1) Override yii\web\Session component:
<?php
namespace app\components;
use yii\web\Session as BaseSession
class Session extends BaseSession
{
/**
* Event name for close event
*/
const EVENT_CLOSE = 'close';
/**
* #inheritdoc
*/
public function close()
{
$this->trigger(self::EVENT_CLOSE); // Triggering our custom event first;
parent::close(); // Calling parent implementation
}
}
2) Apply your custom component to application config:
'session' => [
'class' => 'app\components\Session' // Passing our custom component instead of core one
],
3) Attach handler with one of available methods:
use app\components\Session;
use yii\base\Event;
Event::on(Session::className(), Session::EVENT_OPEN, function ($event) {
// Insert your event processing code here
});
Alternatively you can specify handler as method of some class, check official docs.
As an alternative to this approach, take a look at this extension. I personally didn't test it. The Yii way to do it I think will be overriding with adding and triggering custom events as I described above.

symfony2 my own event

I made the authorization and authentication via facebook like here:
http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html
and it works
Now I want to make my own event, this event will do something when the user authenticates using facebook. For example-will redirect the user to the home page.
I did it like this
http://symfony.com/doc/current/components/event_dispatcher/introduction.html
So I have this class
http://pastebin.com/2FTndtL4
I do not know how to implement it, what am I supposed to pass as an argument to the constructor
It's really simple. Symfony 2 event system is powerful, and service tags will do the job.
Inject the dispatcher into the class where you want to fire the event. The service id is event_dispatcher;
Fire the event with $this->dispatcher->dispatch('facebook.post_auth', new FilterFacebookEvent($args)) when needed;
Make a service that implements EventSubscriberInterface, defining a static getSubscribedEvents() method. Of course you want to listen to facebook.post_auth event.
So your static method will look like:
static public function getSubscribedEvents()
{
return array(
'facebook.post_auth' => 'onPostAuthentication'
);
}
public function onPostAuthentication(FilterFacebookEvent $event)
{
// Do something, get the event args, etc
}
Finally register this service as a subscriber for the dispatcher: give it a tag (eg. facebook.event_subscriber), then make a RegisterFacebookEventsSubscribersPass (see this tutorial). You compiler pass should retrieve all tagged services and inside the loop should call:
$dispatcher = $container->getDefinition('event_dispatcher');
$subscribers = $container->findTaggedServiceIds('facebook.event_subscriber');
foreach($subscribers as $id => $attributes) {
$definition->addMethodCall('addSubscriber', array(new Reference($id)));
}
This way you can quick make a subscriber (for logging, for example) simply tagging your service.
Event object is just some kind of state/data storage. It keeps data that can be useful for dispatching some kind of events via Subscribers and/or Listeners. So, for example, if you wanna pass facebook id to your Listener(s) - Event is the right way of storing it. Also event is the return value of dispatcher. If you want to return some data from your Listener/Subscriber - you can also store it in Event object.

How to get a Boolean return value from jQuery trigger method?

I have a custom event that I want to fire using jQuery's trigger method:
$(wizard).trigger('validatingStepValues');
Then in the wizard's current step code, I subscribe to this event as follow:
$(wizard).bind('validatingStepValues', function (){
// Validating step's form data here; returning false on invalid state.
});
Then in my wizard, again I want to be able to stop user from going to the next step, if a false value is returned from validation process? I'd like to have something like:
$(wizard).trigger('validatingStepValues', validReturnCallback, invalidReturnCallback)
Have you considered using something like:
function wizardValidator(successCallback, failureCallback) {
return function() {
// Validating step's form data here;
if (wasValid && successCallback) {
successCallback();
}
else if (! wasValid && failureCallback) {
failureCallback();
}
return wasValid;
};
}
$(wizard).bind('validatingStepValues', wizardValidator(validReturnCallback, invalidReturnCallback));
This requires that you know the callbacks that you want to use at the time you bind the event listener. If you want to be able to use different callback functions at different times, you could define additional event types, like:
$(wizard).bind('validatingStep2Values', wizardValidator(validStep2ReturnCallback, invalidStep2ReturnCallback));
$(wizard).bind('validatingStep3Values', wizardValidator(validStep3ReturnCallback, invalidStep3ReturnCallback));
Alternately, events that you create by calling trigger() propagate up the DOM hierarchy. Returning false an event handler cancels this propagation. So you could bind your desired success callback function as an event listener on your wizard's parent node. That won't do anything to allow your failure callback to be executed, however.

Resources