If I have a View in backbone.js and it has an event in the events list:
events: {
'click #somebutton': 'clicked'
},
clicked: function () {
console.log('clicked');
}
How can I then disable/enable that event? So for instance if its clicked then
the event is removed (the button remains on screen but is greyed out etc). When some other part of the view is updated or whatever the event
enabled. Sure I can use jquery but I want to know if this functionality is available in backbone.
Thanks for any answers
Paul
You can always use delegateEvents() and undelegateEvents() to redo your event binding between the DOM and your Backbone View. That said, I usually just keep the event handler and add a conditional in the handler.
// .disabled class (CSS) grays out the button
clicked: function(event) {
var buttonEl = $(event.currentTarget);
if (buttonEl.hasClass('disabled')) {
// Do nothing
} else {
// Do something AND...
buttonEl.addClass('disabled');
}
}
Then you can have your other view or code simply removeClass('disabled') when you want to restore functionality.
UPDATE - disabled property
See comments, but a simpler, much better solution is to use the disabled property disabled="disabled" of buttons.
Use delegateEvents and undelegateEvents for binding and unbinding events. Check for reference: delegateEvents
Related
Is there a dismiss event for paper-dialog? I tried dialog-dismiss but it doesn't listen to ESC keyboard press. I tried iron-overlay-close but this one bugs if there is another iron-overlay within the dialog (such as an iron-dropdown)
There is no specific dismiss event for paper-dialog because it inherits the iron-overlay behaviour. However, you could create a custom event to trigger a dialog-dismiss:
// Fire a custom event
this.fire('custom-dialog-dismiss');
// Listen to the event on an element OR add a listener
<my-element on-custom-dialog-dismiss="_handleDismiss"></my-element>
...or...
listeners: {
'custom-dialog-dismiss': '_handleDismiss'
}
// Then handle the action
_handleDismiss: function(e) {
this.$.myDialog.close();
}
I have a button and in my controller i created one mouse over event and a click event for that button's id. But everytime when i click button it goes to the mouseover event function only, but when I comment the mouseover it goes to the click event function nicely. Why this is so? I am using ext4.1
thanks in advance.
me.control({
'#notificationIconId':{
click:me.notificationClick
},
'#notificationIconId':{
mouseover:me.notificationMouseOver
}
});
},
notificationMouseOver : function (){
alert('1')
},
notificationClick :function(menuitem)
{
alert('2')
}
You're using two times the same key '#notificationIconId' in a Javascript object... So, the last one is overriding previous ones.
You can add multiple listeners for the same selector:
'#notificationIconId': {
click: me.notificationClick
,mouseover: me.notificationMouseOver
}
I am using Marionette's CollectionView to render a list of items with ItemViews. Whenever a new item is added, I want to run a short fade-in animation. But not when the collection is rendered initially (or the collection is reset).
Before using Marionette, I handled the reset and add events slightly differently, but I can not figure out how to do this here. I looked at the source code and it seems that addItemView is responsible for adding the child view and both addChildView (called when add is triggered on the collection) and render (for reset events) call this method.
Maybe I am missing something obvious.
This is one way of doing it:
Include these functions in your CompositeView declaration:
onBeforeRender: function(){
this.onBeforeItemAdded = function(){};
},
onRender: function(){
this.onBeforeItemAdded = myAnimation;
}
This is similar to the solution I present in my book on Marionette (https://leanpub.com/marionette-gentle-introduction/)
How it works: Marionette triggers the "before:render" before it renders the entire collection, so you can set the the onBeforeItemAdded function to do nothing. Once the collection has been rendered, set that function to animate the new item view.
Since each time the collection view adds an item view it also triggers the "before:item:added", you can define an onBeforeItemAdded function that will automatically be called when that event is triggered. This matching happens thanks to triggerMethod.
This solution should solve your problem, without your needing to add flags on the model.
David Sulc answer is pretty hacky, fadeIn should be defined within item it self, not within parent view.
Another thing is that onBeforeItemAdded() is not mentioned in documentation, so it could be for internal use and may change over time.
What I suggest is to add following to parent view, note flag parentRendered:
itemViewOptions: function() {
return {
collection: this.collection,
parentRendered: this.rendered
};
},
onRender: function() {
this.rendered = true;
}
and use that flag in onShow function inside item view:
onShow: function() {
// show visual effect on newly added items
if (this.options.parentRendered) {
this.$el.css('opacity', 0).slideDown(200).animate(
{ opacity: 1 },
{ queue: false, duration: 400 }
);
}
else {
this.$el.show();
}
}
I think that your best choice is to bind your event after the CollectionView has been rendered.
myCollectionView.on( "render", function() {
this.on( "after:item:added", executeMyAnimation );
});
events: {
'click .pdf_preview' : 'onPreviewPdfClick',
'click a.next' : '_nextPointer',
'click a.prev' : '_prevPointer',
'mouseleave .mediapop-item-container' : 'onMouseLeave',
'mouseenter .mediapop-item-container' : 'onMouseEnter',
// Editable events
'click &.editable .dialog-header h3' : 'showEditTitleForm' <--- this
},
I create a popup view that has an edit mode. While I could simply extend this view with an editable version, what I need is very basic, so instead I set it up so if you pass this.options.editable the view.el element will have an "editable" class on it.
I am wondering if there is a way for me to specify that selector inside of the event object. That way it won't event trigger if this.options.editable is not true. If Backbone supported a SASS style selector syntax then the above would work. The only alternative is to check for this.$el.hasClass('ediable') within showEditTitleForm.
I know if you set a selector like this:
'click' : 'myAction',
The click event will be applied to the this.el container. I'm looking to only apply the callback if the additional class is there.
Is it possible to do something similar to the above without adding a check within the callback method?
Edit: typo
You can always modify events before delegateEvents is called, just be careful not to modify the events attached to the view's prototype. Something like this:
initialize: function() {
if(this.options.editable) {
this.events = _({}).extend(this.events, {
'click .dialog-header h3': 'showEditTitleForm'
});
}
}
Note the _({}).extend(...), that will merge this.events (which comes from the prototype) and the extra event into an empty object so that you don't accidentally alter the events in the prototype.
Demo: http://jsfiddle.net/ambiguous/dNYXN/
I'm using the rowEditing on my grid in my mvc application. I'm able to handle the event when the user clicks update. However i'm having issues get the selected record. The below behaves strangely. I do not get the record.data.Name value the first time i click update. Tho i can see the value in fire bug.
init: function () {
this.control({
'button[text=Update]': {
click: this.onMaterialUpdate
}
});
},
onLaunch: function () {
},
onMaterialUpdate: function (button) {
var grid = Ext.getCmp('materialsContainer');
var record= grid.getSelectionModel().getSelection()[0];
if (record != null) {
console.log(record.data.Name);
}
}
Not sure about it... but I think the click event happens before completeEdit, thus the record is neither committed, nor updated in the grid (or its selection).
Perhaps try to capture the edit event of the row editor instead of click? You should get the correct record there?
I'd suggested handle edit event of the RowEditor plugin. You could subscribe to this event on grid render event for example. By getting the plugin by pluginId.