stickit doesn't save values from autocomplete fields - javascript

I have plugged autocomplete after in initialize function as advised from stickit documentation.
Almost hello world world example:
MyApp.Views.Form = Backbone.View.extend({
el: "#my-form",
bindings: {
"#postcode_with_suburbs": {
observe: "postcode",
initialize: function($el, model, options) {
$el.autocomplete({
source: [ "c++", "java", "php", "coldfusion", "javascript", "asp", "ruby" ]
})
},
onSet: function(val, options) {
return $("#postcode_with_suburbs").val();
}
},
},
events: {
"click #form-submit" : "submit",
},
initialize : function() {
this.listenTo(this.model, "change");
this.render();
},
render: function() {
this.$el.html(JST['backbone/templates/car_insurance/form']);
this.stickit();
return this;
}
});
So the problem is whenever a user fills the form and autocomletes the postcode by clicking the autocomplete value it is not saved to the model attribute. Saved as ja instead of java
However scrolling down with a keyboard over the options from an autocomplete, the values is set properly to the attribute of a model. Saved as java

The stickit bindings does bind an event listener for change input keyup events on bound DOM element of type <input>. Uses the listener to update the model attribute. The element postcode_with_suburbs, in your case, being an input type should fire change event when user selects one of the option from drop down. I don't know why it is not firing the event. Try this fiddle here See the changes
select: function(event, ui) {
$(this).trigger("change", event);
}
In select event callback of autocomplete, I'm triggering change event explicitly on the element. You can also configure events: [autocompleteselect] instead of select callback.

Related

ExtJS: Field change event fires before ViewController's init

I have a field that is stateful, and I also have it hooked up to the change event... when its value changes, I want to perform some operation. However, because it's a stateful field, the change event fires when I go back to this view, and unfortunately, the change event fires before the ViewController's init method, which means I will not be able to access my reference lookup.
In the following example, run it, change the date, and then re-run the application... you'll see a console.log that appears for the change, and then for the init. I realize I could set up the handler in the init method, but that just seems silly. I also realize I could create myField as a private var and access it that way, but that also seems silly. And yes, I could change to the select event, but that's not what I want to do. Anyone have any thoughts? Here's an example:
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
Ext.define('MyViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.myView',
init: function() {
console.log('init fired', this.lookupReference('myField'))
},
onChange: function(value) {
console.log('onChange fired', this.lookupReference('myField'));
}
});
Ext.define('MyView', {
extend: 'Ext.container.Container',
controller: 'myView',
renderTo: Ext.getBody(),
items: [{
xtype: 'datefield',
value: new Date(),
stateful: true,
stateId: 'blahblah',
listeners:{
change: 'onChange'
}
}, {
xtype: 'datefield',
value: new Date(),
reference: 'myField'
}]
});
Ext.create('MyView');
}
});
This is because the state mixin is initialized before the controller, this is code taken directly from Ext.Component's constructor:
me.mixins.state.constructor.call(me);
me.addStateEvents('resize');
controller = me.getController();
if (controller) {
controller.init(me);
}
There is no config to change this behavior. Honestly, I've never seen someone make a form field's value stateful.
You can use the buffer config to delay event firing.
This has an advantage of setting up the event after the controller is initialised.
The solution:
listeners: {
change: {
buffer: 300,
fn: 'onChange'
}
}
An Alternative is to handle 'beforestaterestore` event of the stateful field and apply the state value only after controller is initialised.
listeners: {
beforestaterestore: function (field, state){
var controller = field.up().getController();
Ext.Function.interceptAfter(controller, 'init', function(){
field.setValue(state.value); // update
},this);
return false;
}
}

Backbone change event not firing when certain attributes are changed

In my backbone application, I have a model that looks a little like this,
{
"id" : 145,
"name" : "Group Number 1",
"information" : "Some kind of blurb about group number 1",
"members" : {[
"id" : 1,
"first_name" : "John",
"last_name" : "Doe",
"email" : "johndoe#goog.ecom"
]}
}
Now if I run this.model.get('members').add(newUser) a new user gets added to the members collection within my model - however it does not fire a change event, why is this? Buy yet if I change the name of the model, then a change event is fired?
All this is done with a view that looks like this,
Individual model view
Views.OrganisationView = Backbone.View.extend({
tagName: 'div',
className:'group group--panel col-sm-3',
template : _.template( $('#tpl-single-group').html() ),
events: {
"click a[data-type=organisation], button[data-type=organisation]" : "edit",
"click .js-delete-group" : "removeOrganisation",
},
initialize: function() {
this.model.on("error", function(model, xhr, options){
console.log(model, xhr, options);
console.log(this);
});
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'destroy', this.removeView);
},
render: function() {
this.$el.html( this.template({
group: this.model.toJSON()
}));
return this;
},
removeView: function() {
this.remove();
},
removeOrganisation: function(e) {
this.model.destory();
this.remove();
},
edit: function(e) {
e.preventDefault();
Routes.Application.navigate('/organisation/edit/' + this.model.get('id'), { trigger: false } );
var editClient = new Views.OrganisastionEditView({
model: this.model
});
}
});
The second confusing thing that a request event gets thrown, (makes sense seen as though I am saving the model, but an error event gets thrown as well, but there are no errors the xhr and I am not currently validating the model?
Here is how I am saving the user to members collection in my model,
var member = new Pops.Models.User({ id: element.data('id') });
member.fetch({
success:function() {
self.model.get('members').add(member);
var model = self.model;
self.$('.search').hide();
self.$('button').show();
var projectMember = new Pops.Views.UserInitialsWithAdmin({
model: member
});
self.model.save({validate:false});
self.$('.search').parent().append( projectMember.render().el );
self.$('.search').remove();
}
});
(I'm assuming the first bit of code you've given is just a guideline of what a plain JSON representation of your model would look like, and that members is a real Collection with an add method available.)
In answer to the first question: change events are only fired when changing a model attribute using set. In your case, you're adding to the collection stored in the members attribute, but the members attribute still contains a reference to the same collection it did before, which means from Backbone's perspective this attribute has not changed. I would suggest attaching listeners directly to the members collection. Also see How can I "bubble up" events on nested Backbone collections?.
In general nesting models in Backbone is not straightforward, as Jeremy Ashkenas has pointed out. It's often better to keep models flat and store references to related models as arrays of ids, which can then be fetched as necessary.

Access <select> onChange in Marionette ItemView

I have a Marionette ItemView like this:
List.Chart = Backbone.Marionette.ItemView.extend({
template: "#chart-template",
className: "block container-fluid first",
onRender: function () {
// Do a few things
},
});
The template has a <select id="filter"> tag with a few options in it. I would like to access the value of the <select> tag when a user clicks it and there has been a change. I'm new to Marionette. I tried a few ways but none got me the value. Thanks.
You will not want to override render in your marionette view, instead you should take advantage of onRender
http://marionettejs.com/docs/marionette.itemview.html#render--onrender-event
As far as knowing when a user has click or changed the input you will want to take advantage of the events hash.
http://marionettejs.com/docs/marionette.view.html#viewevents
Which actually comes from backbone.
So it will look like this:
List.Chart = Backbone.Marionette.ItemView.extend({
template: "#chart-template",
className: "block container-fluid first",
events: {
"click #filter": "doSomething",
"change #filter": "doSomething"
},
doSomething: function() {}
});
For extra points you should DRY up the event binding and take advantage of the #ui interpolation that backbone.marionette gives you for free.
List.Chart = Backbone.Marionette.ItemView.extend({
template: "#chart-template",
className: "block container-fluid first",
ui: {
"filter": "#filter"
},
events: {
"click #ui.filter": "doSomething",
"change #ui.filter": "doSomething"
}
});

Jquery Event handler not working when calling from page

I have written an event to save the data in a widget.js file & the handler is on the page. There is no error or exception is coming but the handler is not getting called. Please help.
Widget.js :
(function ($, undefined) {
$.widget('ui.discussionwidget', {
options: {
userID: 'arti.agarwa',
title: "",
width: "",
containerClass: ".ui-content-gutter"
},
saveData: function (userName, msg, parentID) {
//Save Discussion History
$.event.trigger({
type: "sendMessage",
userName: userName,
message: msg,
parentID: parentID,
timeStamp: new Date()
});
},
});})(jQuery);
Page Script :
$(document).ready(function () {
$('#discussionwidget').live("sendMessage", sendMessageHandler);
// sendMessage event handler
function sendMessageHandler(e) {
debugger;
alert(1);
}});
Looks like event delegation is not working fine with global events
$('#discussionwidget').on("sendMessage", sendMessageHandler);
Demo: Fiddle
I can see two possible problems:
Your widget has class discussionwidget but you are binding with id discussionwidget.
You are creating the widget dynamically with javascript? May be the event is being bound before the widget is created.
Try to fix both.

Backbone.View with jQuery Editable Plugin

I am trying to use jQuery Editable Plugin in my Backbone.View Object in Symfony2.
When I perform dblclick on DOM element which class is editable it turns in input element as I wish.
Then when I perform keypress I get three issues:
No route found for "POST /[object Object]" 404 Not Found - NotFoundHttpException
the key entry "name" for the model turns to empty string.
the view does not change
My goal is to change the backbone.model and then automatically the view.
var MyView = Backbone.View.extend({
events: {
"dblclick .editable": "edit",
"keypress .editable": "updateOnEnter"
},
edit: function edit ()
{
$(this.el).find(".editable").editable({type:'input'}); // it works
},
updateOnEnter: function updateOnEnter (e)
{
if (e.keyCode == 13) {
this.close();
}
},
close: function close ()
{
this._model.set({
name: $(this.el).find(".editable").text()
});
}
});

Categories

Resources