I'd would like to do something like backbonejs events, define an events object within the controller, something like this:
var UserController = function() {
this.events = {
'click .display': 'displayUsers',
'click .delete': 'deleteUsers'
}
this.displayUsers = function() {
//display users
}
this.deleteUsers = function() {
//remove users
}
}
After that, do something with requirejs and load the controller on demand and append the events, the code is almost ready but the events is something i can't resolve. Someone can help with any idea to do this?.
My idea is take the events object after controller class is loaded and send it to an event manager or something to create the events on the fly.
Related
I know (mostly) how to react to the various events fired by that menagerie of objects living inside the DOM.
To notch things up a bit, I'd like to be able to fire my own bespoke events when appropriate, something I suppose I could pseudo-code as follow :
myObject = {
prop:{ soAndSo }
method : function(args){
//do some stuff that takes forever
"All done and ready, now tell the world"
}
}
The idea being of course that some time down the road I can instantiate a myObject, then even later monitor its behaviour with something to the effect of
aMyObject.onmyevent = function(event){
//do something appropriate for the circumstance
}
The thing is, I have no clue as to where to start regarding the part "now tell the world".
Will you point me in the right direction?
You need to create a faux eventEmitter. Here is one I made while following a tutorial from Pluralsight called React and Flux for Angular Developers: Tutorial
To your question, you 'tell the world' by emitting the event, which is essentially calling all the active listeners you have.
// make your own emitter:
function EventEmitter () {
// holds events buy type; ex:'ADD_TODO'
this._events = {};
}
EventEmitter.prototype.on = function(type, listener) {
// add events to listen for
this._events[type] = this._events[type] || [];
this._events[type].push(listener);
};
EventEmitter.prototype.emit = function(type) {
// emit event base on type
if (this._events[type]) {
this._event[type].forEach(function(listener) {
// call listeners for events:
listener();
});
}
};
EventEmitter.prototype.removeListener = function(type, listern) {
if (this._events[type]) {
this._events[type].splice(this._events[type].indexOf(listener), 1)
}
};
I am trying to implement endless scrolling with Backbonejs. My view initializes a collection and calls fetch fetch function.
My view
var app = app || {};
app.PostListView = Backbone.View.extend({
el: '#posts',
initialize: function( ) {
this.collection = new app.PostList();
this.collection.on("sync", this.render, this);
this.collection.fetch();
this.render();
},
render: function() {
/*render posts*/
}
});
In my page I added the following code. It checks if the the user at the bottom of the page. If yes then it checks if the view is initialized. If yes then call that view fetch function of the view's collection object.
var app = app || {};
$(function() {
var post_view;
$(window).scroll(function() {
if(($(window).scrollTop() + $(window).height() == getDocHeight()) && busy==0) {
if(!post_view){
post_view = new app.PostListView();
} else {
post_view.collection.fetch();
}
}
});
});
So far this code is working. I am not sure if this is the right approach or not?
It's not a bad option; it works, and Backbone is making that collection available for you. But there's a couple of other options to consider:
Move that collection.fetch into a method getMoreItems() inside your PostListView, and call it within your else block. That way you're encapsulating your logic inside the view. Your app is more modular that way, and you can make your scrolling smarter without updating the rest of your app.
Move the scroll listener inside your PostListView. I'd probably put this within your PostListView's initialize function. Again, this reduces dependencies between the various parts of your app - you don't have to remember "Whenever I create a PostListView, I must remember to update it on scroll." By setting that event listener within the PostListView itself, all you have to do is create it. Backbone's general philosophy is to have small, independent components that manage their own state; moving the event listener inside would fit with that.
I am still kind of new to backbone and I have a question. I am currently working on a previously created backbone view. This view is responsible for all the saving within the application. The class is becoming exceedingly large and I wanted to split out some of the events/methods/function to their own "sub class", if that is possible. For example, I have a group of events and functions that are responsible for a specific task. I would like to move those event and functions to their own js page, in a sub folder. The problem is that the events are being called. Here is a general overview of how the class is setup:
var myClass= myClassBaseClass.extend({
events: {
.... all my events here,
'click .eventOneButton': 'eventOne',
},
initialize: function (options) {
//initialize stuff here
},
postRender: function (renderOptions) {
//post render here
},
preRender: function (renderOptions, html) {
return html;
}, template: function (renderOptions) { //template stuff },
//...etc.
//my events
//eventOne was here, now its moved to its own file
});
My new file is in a subfolder, and looks like this:
var myClassSubClass= myClass.extend({
eventOne: function(e){
//event stuff here
}
});
So, is what am I doing wrong? Why wont the event get caught in the second file?
thanks
jason
I want to trigger a backbone event when the view has rendered. Ideally, I'd write something like this:
var DetailView = Backbone.View.extend({
id: 'detailpage',
events: {
'ready document': '_bringSlideDown',
'click .close-slideDown': '_closeSlideDown'
},
and I would be able to create and call a _bringSlideDown function once the view has finished loading. This doesn't work - is there a better way to call this event?
Specifically, I want the event to only run once, which is why I'm not nesting it in the render function. I want the view to be able to render multiple times, but want to use Backbone's .off() method to handle this event once before unbinding it. Thanks!
I have three points that I want to mention.
First, by best practice I execute Backbone code until the DOM is
ready, so if you follow this rule, your backbone view will be
executed after the DOM was ready(so there is no way to listen for the ready event).
If you want to listen for DOM additions with jQuery, you should use
plugins like: https://github.com/brandonaaron/livequery
Regarding your use case, instead of listen to the DOM, check in the render
method if is the first time that you are rendering the view using
a flag.
I would do something like this:
var YourView = Backbone.View.extend({
_rendered : false,
events : {
'click .close-slideDown': '_closeSlideDown'
},
render: function(){
//some render stuff
if( !this._rendered ){
this._rendered = true;
this._bringSlideDown();
}
}
});
Basically
I wanna know if there is anyway to depend event binding with "if" in Backbone.
For example, if i have user profile model and i want to bind "Send Message" button event only if the attribute "acceptMsgs" sets true.
My current solution is to check it in the event firing, if there is better way, pls correct me.
I'm not sure if it's a better way to do it, but you can use a function that returns a hash for the event hash (and of course in the function you can check for some condition).
For example something along the lines of
myView = Backbone.Views.extend({
events: function () {
if (someCondition) {
return { "#someButton click" : "nameOfFunction"}
}
}
//the rest of your view
});
Alternatively you can forgo the event hash and bind your events in the initialize method, for example
initialize: function (options) {
if (someCondition) {
this.$el.on("click", "#someButton", nameOfFunction);
}
}