How to monitor change in input in backbone?
In AngularJs
<div ng-controller="W3">
<input type="text" ng-model="val" >
<p>{{val}}</p>
</div>
I want that field value has been displayed in <p></p>.
You have to add it as an event on your view:
var MyView = Backbone.View.extend({
events: {
'keyup input': 'updateParagraph'
},
updateParagraph: function(ev) {
this.$('p').html(ev.target.value);
}
});
This assumes that your HTML for the view is just like what you have in your question. If you want to use multiple events, you will need to add each one to the hash. Like:
events: {
'keyup input': 'updateParagraph',
'propertychange input': 'updateParagraph',
// etc.
}
And if your view is tied to a model and the input should update the model, I would write it this way instead:
var MyView = Backbone.View.extend({
initialize: function() {
this.listenTo(this.model, 'change:text', this.updateParagraph);
},
events: {
'keyup input': 'updateModel'
},
updateModel: function(ev) {
var target = ev.target;
// Assuming that the input name is the model attribute
// To simplify, I'm just going to set something specific
this.model.set('text', target.value);
},
updateParagraph: function(model, value) {
// Set the input value as well, so it stays in sync
this.$('input').val(value);
this.$('p').html(value);
}
});
That makes it so that if you change that attribute on the model in any other view, the paragraph would still update, regardless of whether it was that input or not.
Related
I am using Backbone.js with stickit for binding. I have something like below. How do I know which element the user has clicked? (Radio buttons)
initialize: function() {
this.listenTo(this.model, 'change', this.blockDiv);
}
blockDiv : function() {
console.log('The changed element is '+); //How do i know which element the user has changed?
}
bindings : {
'[name=element1]' : element1,
'[name=element2]' : element2
}
You are listening changes from your model, not DOM events directly. You can check what attributes of model have changed with changedAttributes.
I'm trying to build a view that will initially display text. If the user double-clicks, it will replace that text with an input field. This way the user can easily update the text (like using the "contenteditable" attribute).
I have an approach that works in Ember pre4, but not in Ember RC1. In RC1, the Ember.TextField does not initialize to the parent view's value property. When you double-click the label text, it creates an empty input field. Here are two fiddles:
Pre4 (working): http://jsfiddle.net/mattsonic/cq5yy/5
RC1 (same code - not working): http://jsfiddle.net/mattsonic/UUac9/15
Any idea what changed inside Ember? Thanks.
Here is the code:
App.InputView = Ember.TextField.extend({
classNames: ["input-small"],
valueBinding: "parentView.value",
didInsertElement: function () {
this.$().focus()
},
focusOut: function () {
parent = this.get("parentView");
parent.setLabelView();
}
});
App.LabelView = Ember.View.extend({
tagName: "span",
template: Ember.Handlebars.compile("{{view.value}}"),
valueBinding: "parentView.value",
doubleClick: function () {
parent = this.get("parentView");
parent.setInputView();
}
});
App.LabelEditView = Ember.ContainerView.extend({
tagName: "span",
labelView: App.LabelView.extend(),
inputView: App.InputView.extend(),
didInsertElement: function () {
this.setLabelView();
},
setInputView: function () {
this.set("currentView", this.get("inputView").create());
},
setLabelView: function () {
this.set("currentView", this.get("labelView").create());
}
});
I found a solution that I don't like at all. But, it solves the problem as described.
focusIn: function() {
var val = this.get("parentView.value");
this.set("value", "");
this.set("value", val);
},
If you set the input field's value to the correct value during the focusIn event, it still fails. But, if you set the input field's value to a different value and then switch it back, the input field will appear with the correct value.
I would love to know a better way to solve this problem. The Ember pre4 solution is more much elegant than this.
Working fiddle: http://jsfiddle.net/mattsonic/UUac9/19/
I'm trying to hook up a checkbox to my View, but as soon as I tick it, it stays checked, even when I click it again?
Here's part of the View:
views.PaginatedView = Backbone.View.extend({
events: {
'click input.completedEnquiries': 'filterCompletedEnquiries'
},
filterCompletedEnquiries: function (e) {
return e.currentTarget.checked;
}
});
Heres the template:
<label>Show Completed: <input type="checkbox" class="completedEnquiries" /></label>
I've no idea what I'm doing wrong here?
Edit
Here is a Jsfiddle of the problem: http://jsfiddle.net/9cvVv/167/
The problem is returning e.currentTarget.checked from your event handler. Returning true or false from this handler will check or uncheck the box for you
filterCompletedEnquiries: function(e) {
//return e.currentTarget.checked;
},
comment out that return statement, and it works fine. You can still grab the info, but don't return anything from the method.
filterCompletedEnquiries: function(e) {
var isChecked = e.currentTarget.checked;
// do stuff here, based on it being checked or not
},
Edit
Here's an example, based on the conversation in the comments:
views.PaginatedView = Backbone.View.extend({
events: {
'click input.completedEnquiries': 'completedEnquiriesClicked'
},
// this is explicitly an event handler, and that's all it should be used for
completedEnquiriesClicked: function(e){
this.showCompletedEnquiries = e.currentTarget.checked;
},
doSomething Else: function (e) {
// now that we need to know, we can just check that attribute
if (this.showCompletedEnquiries){
// do something here
}
}
});
This is just one of many options you have, for making this work the way you want.
I have a edit in place section to which I want to add a confirmation of changes before the knockoutjs model is updated.
Here's the jsFiddle example of what I have now.
Here's what I would like it to do.
User clicks on editable section
textbox appears with save/cancel buttons next to it.
if user makes a change and clicks save, view model is updated
if user makes a change, but decides to keep the original content, they click cancel, view model remains unchanged, texbox is hidden, and editable element remains unchanged.
The behavior of the cancel click is what I'm not sure how to implement. Can anyone suggest how this could be done?
I prefer to use custom binding handler for this.
Example http://jsfiddle.net/7v6Dx/10/
Html
<div>
<span class="editField">
<span data-bind="text: Address1">Click here to edit</span>
<input type="text" data-bind="clickEditor: Address1">
</span>
</div>
JavaScript
ko.bindingHandlers.clickEditor = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var $element = $(element).hide();
var $text = $element.prev();
var $buttons = $("<span class='editConfirm'> \
<button class='saveEdit' type='button'>Save</button> \
<button class='cancelEdit' type='button'>Cancel</button> \
</span>").hide().insertAfter($element);
var $editElements = $buttons.add($element);
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$buttons.remove();
});
var _toggle = function(edit) {
$text[edit? 'hide' : 'show']();
$editElements[edit? 'show' : 'hide']();
}
$text.click(function(e) {
_toggle(true);
});
$editElements.find('.saveEdit').click(function() {
_toggle(false);
valueAccessor()($element.val());
});
$editElements.find('.cancelEdit').click(function() {
_toggle(false);
$(element).val(ko.utils.unwrapObservable(valueAccessor()));
});
}
, update: function (element, valueAccessor) {
$(element).val(ko.utils.unwrapObservable(valueAccessor()));
}
};
$(document).ready(function() {
var helpText = "Click here to edit";
function appViewModel() {
this.Address1 = ko.observable(helpText);
}
ko.applyBindings(appViewModel());
});
I was thinking you could probably use a writable computed property to handle this. But it might be easier to just have to separate properties. One property is the real property and the other shadows it. When you bring up the editable section, it's actually bound to the shadow value. When the ok button is clicked, you copy the shadow value to the real value. If cancel is clicked, you do the opposite (copy the real value to the shadow value).
I'm trying to capture the key event from a view as follows:
myView = Backbone.View.extend({
el: $('#someDiv'),
initialize: function(){
// initialize some subviews
},
render: function(){
return this;
},
events:{
'keypress #someDiv': 'showKey'
},
showKey: function(e){
console.log(e.keyCode);
}
})
That does not work ?
ps: There a no [input] elements in the view or its subviews. I just need to know if the user presses any key and then do something on the view.
You can do this in the view initialize() function:
_.bindAll(this, 'on_keypress');
$(document).bind('keypress', this.on_keypress);
Key pressed goes to the focused element on the page. If you have nothing in your view and the view does not have any focus, then you will not have any key press events.
( btw if you want to do key press event for this.el, do "keypress" : "showKey" )
In you above code the body will most likely receive all keypress events.