I'm trying to trigger some events at initialize in my views. They work if I back and forth in the browser or if I load a second view, but not at first loading, i.e. when the user lands in the view.
My setup is as follows:
I create an event aggregator at router.js like:
socketEvents: _.extend({}, Backbone.Events)
Then I pass the aggregator to each view like:
index: function() {
this.changeView(new IndexView({socketEvents:this.socketEvents}));
},
Then in index.js I do something like so:
initialize: function(options) {
this.socketEvents = options.socketEvents;
this.socketEvents.trigger('one:event');
},
As I said, if I refresh the page doesnt work, if I move to another view and hit back in the browser, the event is triggered.
Why is this happenning? How can I solve this?
Thanks
Editing after first comment:
There are not errors I can/know how to track. At initialize() Either it just does seamlessly the whole transaction: trigger and listenTo, or it completely ignores it at initialize(). Order of execution is as follows: I boot the application with require, from there it loads a class with the router and socket.io client. Then it iniatilizes the socket.io client and uses the router event aggregator. Then it checks if the user is logged, if it is, it triggers an router.event saying the user is logged in. At the socket.io client, there is an event.Dispatcher binding the logged in to initiating the socket. Finally the user is redirector to a index view. Then it happens as I described above.
Related
I have a simple requirement where out of multiple pages, I have one Settings page in Ionic app, where I am allowing the user to toggle one data(say, language) that is maintained in LocalStorage in the app(via a factory).
This 'language' is used in all views(controllers).
I have Back button on the view but when user changes 'language' through Settings page(I update LocalStorage) and want to go back through IonicHistory back button to the preview view, change does not show up after going back.
"Previous view" uses LocalStorage.Language to fetch data
Back button uses following code:
$scope.goBack = function() {
window.history.back();
}
Can anybody help here or any workaround for this is possible.
Ionic caches views in the current navigation history. In order to update the view everytime you come to a view, you should use $ionicView lifecycle callbacks like .enter, .beforeEnter etc. The code written as part of these callbacks are executed everytime even if the view was cached:
$scope.$on('$ionicView.enter', function() {
// Get your settings data here to reflect it on page everytime
})
For details refer: http://ionicframework.com/docs/api/directive/ionView/
This is not my actual use case, but I am trying to understand the concept of how to load a view based on the information another view has using appgyver supersonic framework.
I have 3 pages, Login.html, MainPage.html, and Load.html. Each of them have their own controller. When the app opens it first goes to the login page. The login page sends the username and password to my server which then returns success or not. When there is success, the app goes to the main page. I would like for the load.html to understand a login has happened and start loading the view with the users appropriate content. This is so when the user goes from the main page to the load page all the information is already loaded. I am trying to understand the concept of how to accomplish this with supersonic.
You can use publish / subscribe methods between controllers.
Check out this doc for some good examples.
Basically, you want to publish a message with some data when the user is logged in. Your controller for after log in will be able to listen or subscribe to that message. When it receives the message it will be able to run any code you tell it in the callback.
One controller will publish:
// gather some user data with successful login like var id = result.user.id
supersonic.data.channel('loginSuccess').publish({ userid: id });
Another controller will listen:
supersonic.data.channel('loginSuccess').subscribe( function(data) {
$scope.id = data.userid;
// load some data based on user id
});
You can preload the views as well. This may help speed things up. If you don't, you may see a spinner in between view pushes. In structure.coffee in the config folder:
preloads: [
{
id: "viewIdYouSet"
location: "nameOfModule#view"
}
]
When the login finishes, you can find the preloaded view and push it to the stack:
supersonic.ui.views.find("viewIdYouSet").then( function(startedView) {
supersonic.ui.layers.push(startedView);
});
Hope this helps.
I am using AngularJS 1.3. Assume I have created several routes in my application. But when user hits a specifc route/url & then tries to move to another route/url, I want to fire some event. I do not want to fire this event on every URL change.
So only when user comes out of this url http://localhost:9000/data/55677c/edit, I want to fire one function available in XYZ controller.
Here is my scenario:
I have a page which looks like this:
<div class="well">
<button id='edit-btn' type="button" ng-click='saveContent()'>
<div ng-include="'components/grid/comOne.html'"></div>
</div>
components/grid/comOne.html page contains one grid and it has its own controller which takes care of data management of the grid.
This grid is shown in two pages. One in editable mode and one is non-ediatble mode. While user is in editable mode and try to move out of the page without saving the info, I need to fire an event in order to discard ant changes user has made to the grid data.
Please suggest
If the listening controller is a parent controller you could $emit the event.
Or you could have a common service like this:
angular.module('x').factory('CommonLogic', function(){
var pageChangeListeners = [];
return {
listenToPageChange: listenToPageChange
};
function listenToPageChange(callback){
pageChangeListeners.push(callback);
}
function pageChanged(){
for(var i = 0; i < pageChangeListeners.length; i++){
pageChangeListeners[i]();
}
}
});
then when leaving that url (track that via $routeChangeStart) you can call: commonLogic.pageChanged()
In the controller where you want to take action just:
commonLogic.listenToPageChange(function(){..}).
Obviously this should be improved to avoid duplicate registration of the listener ... etc.
I hope I'm not overcomplicating this. Could you describe your use case in more detail ?
I guess you want to use $routeChangeStart:
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
});
You can put this in the scope of your current controller which might be edit as your url says.
From the docs:
$routeChangeStart
Broadcasted before a route change. At this point the route services starts resolving all of the dependencies needed for the route change to occur. Typically this involves fetching the view template as well as any dependencies defined in resolve route property. Once all of the dependencies are resolved $routeChangeSuccess is fired.
The route change (and the $location change that triggered it) can be prevented by calling preventDefault method of the event. See $rootScope.Scope for more details about event object.
Type:broadcast
Target:root scope
I am using Browserify (kind of like AMD)
In view event handler, after password is verified, I'd like to send a message 'login_success' to router to change route.
In the route 'login_success' handler, I'd like to call route.navigate('/newRoute'), which is function extended from Backbone.
But I haven't figure out how to send message from view to router. Can anybody share a sample code or a link?
Is there any best practice to change route in Backbone?
Thanks!
Personally I like to go the route of triggering an event that your router is listening to and then acts upon.
So say in your view you could say
onPasswordVerified: function() {
this.trigger "password:verified"
}
Then in the controller you can listen to that event (note sometimes this is prefaced with childview depending on if you are listening to a collection/composite view, but I doubt you are with a login page):
this.listenTo(loginView, "password:verified", function(args) {
App.vent.trigger "password:verified"
});
Lastly in your router you listen to that event (I usually build a navigate function into my App object which does Backbone.history.navigate in the background):
App.vent.on "password:verified", function() {
App.navigate("/users");
API.userProfile();
}
The great thing about this is if there are other parts of your app that should listen to this event, they can then act accordingly. Also routing this way lets you update your url/route to the page as if you'd done a Backbone.history.navigate({trigger: true}) just without the associated 'refresh the page' server call.
The most straight forward way is just use Backbone.history.navigate() .
If you rather have some local authority for navigation you could do something as
App.execute("navigate:to", "/url")
and implement it as you see fit:
App.commands.setHandler("navigate:to", function(url){
...
Backbone.history.navigate(url)
})
i'm developping a sample single web-app and i discover Chaplin.js.
I had implemented a simple login form, and create in application.js (as given example) in intiMediator method:
Chaplin.mediator.user = new User();
and subscribe for login event in loginController to redirect to internal pages when event is catched
Chaplin.mediator.subscribe('login', this.test);
finally when user submit login form in loginView i'd wrote
Chaplin.mediator.user.set({"name":this.model.get("name"),"age":this.model.get("age")});
Chaplin.mediator.publish('login',this.model);
And all went ok until i click on browser back button to return to login form. When resubmit the form neither mediator.user has an user obj nor the controller has any subscripion.
Has anyone any tips?
Tks
As stated in the Chaplin.js docs "If you want to give local pub/sub functionality to a class, take a look at the EventBroker."
Adding pub/sub to a class:
In your User class, you can mixin to add pub/sub functionality by using Underscore's _.extend:
module.exports = class User
_.extend #prototype, Chaplin.EventBroker
constructor: (options) ->
#subscribeEvent 'login', #test
# ...
Persist data between routes:
Now, persist data across routes is another story and you can approach that in many ways depending on your needs. For example, you may know that you can persist a Chaplin.View and its related data using Chaplin.Composer
Also, you have plenty of useful tools to keep track of the disposal process. For example you have beforeControllerDispose event that is emitted before current controller is disposed.
You could subscribe this event to keep some desired data persisted between routes with the help of a static class. For example, subscribe your Controller to the beforeControllerDispose event:
# in Controller..
#subscribeEvent 'beforeControllerDispose', #beforeDispose
# ...
beforeDispose: ->
MyStaticClass.user = #user
# ... you can do some extra cleanup here.
# useful for unbinding stuff that you know it will not be garbage collected/disposed
And then, use Chaplin.Controller.beforeAction method to ensure that your object is available from the very begining. beforeAction, as its names indicates, is automatically called by Chaplin before calling the action (index, show..) of your actual route/endpoint, so you can use it to pre-assign some data:
# in Controller..
beforeAction: ->
#user = MyStaticClass.user
# ...
index: ->
# #user is available here