Backbone.js Router and back button check - javascript

Basically, I am trying to check if the previous page on every route was equal to one specific page on my site. If it is, then I want to keep the person on that view, otherwise, they can proceed to the other view.
Is there a way in a Backbone.js router, to fire off a global event that will fire before the route callback is executed?
Or, is there a way to have a catch all route that does some checking then forwards to the appropriate route.

I think overridding Backbone.History.navigate and only invoking the superclass method conditionally might work. You could also add an additional event handler for window.hashChange and window.pushState events wired up before the backbone history, and prevent the default propagation of those events if your criteria match.

Related

Is there a way to run a specific function before moving or refreshing pages in angular?

When a page is routed to another page or when a user presses the Back, Forward, or Refresh buttons, the alert window is displayed and the user selects Move, and the user wants to proceed with the initialization process.
For unload events, this does not occur in page routing. Attempted to use canDeactivate, but failed to execute a specific function after closing the alert window.
I want to know the detailed method and example.
(I'm not familiar with the anglular)
Yes. I can think of two potential solutions to your problem:
-1- If you are using Angular Material Dialog combined with canDeactivate guard logic there is a built-in method just called like that. It is named beforeClosed. It returns an Observable that you can subscribe to which will notify you when the dialog started closing. Inside this method you can execute your function.
-2- Angular router has an API called events. It essentially helps you track the status of the router. It can detect when the router starts the navigation, ends the navigation, cancels the navigation, resolved the navigation, etc...
For a complete list of API advanced events. Check this documentation link
Cool, with this API you can choose the right event that suits you and put you function inside the condition such as :
checkRouterEventToFireCustomFunctionLogic(){
this.router.events.subscribe((routerEvent) => {
if(routerEvent instanceof NavigationStart) {
// execute my custom function OR
// just console.log("Hello World")
}
});
}
PS: beforeunload event is not really good especially when it comes to Web Vitals bfcache

How to dispose of a viewmodel in Durandal after deactivation

I am using durandal and requirejs to compose my viewmodels. I am also hooking into the composition life-cycle callback method deactivate every time I navigate away from the view. I want to dispose of my viewmodel in this method.
I've tried delete this, this = undefined but they don't seem to work.
I am also using the durandal event aggregator like this:
self.activate = () => {
App.trigger("testEvent");
};
App.on("testEvent").then(() =>
{
alert('Event Triggered!');
});
So every time the viewmodel is loaded, the event will be triggered. Now, if I the navigate away from the view, then navigate back (hence the viewmodel will be loaded again), then the event will be triggered twice. If I navigate to the view for the 3rd time, the event will be triggered 3 times and so on and so forth. So the previous viewmodels are still present, which is why the the durandal event is being triggered by each viewmodel. Therefore, to fix this issue, I need to dispose of the viewmodels in deactivate, how can I do this?
Note. the viewmodels in question are transient, not singleton.
Durandal also provides an "attached" lifecycle hook which only gets triggers when the view is attached in the DOM. If you place your event subscriptions here they should only get subscribed to the one time.
http://durandaljs.com/documentation/Hooking-Lifecycle-Callbacks
EDIT:
As far as unsubscribing from events goes, if you save the return value from the subscription you can call .off later in your deactivate or detached methods
var subscription = App.on("testEvent");
...
subscription.off();
http://durandaljs.com/documentation/Leveraging-Publish-Subscribe.html
The viewmodel itself is just a managed javascript object and will be disposed automatically after all references to it disappear.
It's probably keeping a reference to your view model because you are subscribing to the event 'testEvent' but never unsubscribe. I'm not an expert in how it would dispose in javascript but have come across similar scenarios in .net
Your event won't get triggered three times, it would get triggered once but the event handler function will get called per subscription so after 3 navigations, 3 times.
Try unsubscribing in the deactivate method and see if it works. This will at least stop the event handler firing three times. I'm not certain this will dispose of your view model correctly though.

alert user when leaving route in Ember 2.0

Ok so i have a component i made up with a form. I would like to alert the user that he has unsaved data (if he has) when the user clicks on another link.
Now if i would not be tied to ember i would put a flag on a change event and add a window unload listener to show the actual message, However,
Since im not really leaving the window this is not getting called.
Is there any Ember event i can attach a handler to? like a change route intent event of some kind
Im interesting in knowing which is the correct event for the leaving route action, not in the something change logic.
ive tried this so far on the didInsertElement( ) method
Ember.$("body").on('unload',()=> alert('it works'));
Ember.$("window").on('unload',()=> alert('it works'));
Ember.$("body").on('unload','body'()=> alert('it works'));
any ideas?
Have you had a look at the willTransition method on your route? That will be the place to do it. Have a read of this guide to preventing and retrying transitions, as well as the willTransition method's documentation. Hope that helps!
You can catch transition event on route. It's meant to be used for this use case.
There is also action when component is being destroyed but that is meant for teardown.

Insert temporary DOM element for onClick hander

I've an HTML table generated by React render() which is tied to a websocket for realtime updates.
What I'm looking to do is attach a React event handler "onClick" to the cell which replaces the value in the cell with a custom piece of DOM such as some Bootstraps dropdown HTML so the user can update that cell.
I can use .getDOMNode() in the click event handler and then manipulate the DOM manually and insert the code, however if render() on this component was called due to a new updated state from a websocket event it would be overridden. If this race condition occurs, I need to inform the user instead of the DOM simply being replaced. I've just seen componentWillUpdate() though this still feels like I'm not using React correctly.
Is there a better approach ? It feels dirty to be manipulating the DOM and incorrect to change the state.
Updating internal component state is there for exactly this case. This component should be in charge of determining whether it is active or not. If you update state on the component when the click handler is triggered with something like active: true, then you trigger a re-render. In your render function add the additional DOM elements if active is true. Then you have three different possibilities that should be accounted for:
onBlur
onUpdate which can
be triggered in two ways. either way you'll likely want to set
active: false on state.
websockets - you will need to inform your
user here probably regardless of if the component is active or not
user - which will just update normally
Doing it this way means that React is always in full control of the DOM, which is a really good way to avoid issues with React.

Is there a rule of thumb to decide when to use trigger or triggerMethod in Backbone.Marionette?

I'm playing a bit with Backbone.js and Backbone.Marionette and I would like to know what's the difference between trigger and triggerMethod.
In particular, is there any rule of thumb to decide when use the former or the latter?
In my mind events, for example, are useful to communicate between a DOM element and its view.
triggerMethod is used in Marionette to update in cascade different components, e.g. a layout calls the show method to its children (children respond to onShow). So, for me its the same as calling a direct method on it. Is this true?
What about trigger?
Thanks you in advance.
There isn't a huge difference, and it simply depends on what you want to do...
trigger will trigger an event
triggerMethod will trigger an event AND call a corresponding method according to naming convention (see https://marionettejs.com/docs/v2.1.0/marionette.functions.html#marionettetriggermethod)
Obviously, if you only want to trigger an event, you'd use trigger. But using trigger you also create a "home made" triggerMethod implementation: trigger the event, then have a listener that will call the function you want.
So what about triggerMethod ? As mentioned above, it will trigger an event and call a method. So if your only objective is to call the method in the first place, there isn't necessarily a need for using triggerMethod.
So why would one use triggerMethod at all? Because it gives you "hooks" to add functionality with event listeners. In my book on Marionette, for example, there is a triggerMethod call in https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/apps/contacts/edit/edit_controller.js#L24 to display error messages on a form. The same could be achieved by simply calling
view.onFormDataInvalid(contact.validationError);
But as mentioned above, triggerMethod give us a "hook" for later use. For example, let's say I want to add logging of user errors: I can simply add a listener to my view:
initialize: function(){
this.on("form:data:invalid", function(validationError){
// log error here
}
}
This additonal functionality can be added without impacting the rest of the code, because we've used triggerMethod instead of a direct method call. In addition, it will be easier to test later (small tests, with single point of failure):
test that "form:data:invalid" event is triggered when a user enters incorrect info
test that when "form:data:invalid" event is triggered, error gets logged
etc.
trigger(name)
Part of Backbone.js
Triggers event using the name passed in
triggerMethod(name)
Part of Marionnete.js
Does everything trigger(name) does
Also calls methods using a predefined naming convention.
eg. triggerMethod('foo') will call onFoo()
eg. triggerMethod('foo:bar') will call onFooBar()

Categories