Backbone.js model validate method fails to fire - backbone.js

I'm trying to understand how Backbone.js model validation works, but I'm seeing some odd inconsistencies. In one place in my app, the validate method is getting called as expected. In another place, however, Backbone.js seems to be passing in a { silent: true } object to the validator, even though I don't want it to.
Here's a jsFiddle that illustrates the issue. The validate method should be called When the Copy buttons are clicked or the values change, but when I step through the code it's clear that the _validate function is being passed the { silent: true } option.
What am I missing?
Update: Figured out what was going on here. I created this jsFiddle originally to replicate an issue I was having that was actually the opposite of this question--I was trying to add an empty model to a collection and validation was firing and preventing me from doing so. When I made the Fiddle, though, it worked as I wanted my app to work. Validation wasn't firing when an empty model was added. I couldn't figure out the difference.
Turns out I was using Backbone.js 0.9.0 in my application and version 0.9.1 in my jsFiddle. Jeremy made changes to validation in 0.9.1 to make it work the way I wanted it to work in my app (see this issue on GitHub). Mystery solved.

Backbone specifically does not call _validate when you're making a new model.
Jeremy suggests that you do:
var mymodel = new MyModel();
mymodel.set({params});
Here's our exchange on github: can't override silent:true

From the Backbone docs, it seems you have to either call set or save on the model in order for validate to trigger.
I updated the jsfiddle so that set is called, and the now the validation function gets triggered:
http://jsfiddle.net/J3uuH/12/

Related

How to trigger a function when a MongoDB Cursor property is changed? (Angular-Meteor)

I don't know if i titled my question correctly but here is what i want to achieve and what i have so far (simplified as much as possible):
What I have so far:
For each Visitor I create a "Visitor" Object:
{
name:"Bob",
mouseX:"31", // The mouseposition is constantly updated
mouseY:"400",
messages:[
{text:"Message Text",prop:"other property"},
{text:"Another Message"}
]
}
After that I bind the Object to the scope:
$scope.helpers({
visitor: () => Visitors.findOne({"_id":id})
});
The Messages are shown inside a ng-repeat over the visitor.messages model:
<div ng-repeat="msg in visitor.messages">
<span class="text {{msg.class}}"> {{msg.text}} </span>
</div>
Another Visitor can send a new Message with:
Visitors.update(
{_id: visitor._id},
{$push: {messages: {"text":"New Message"}}}
);
What I want to do
When Bob receives a new message i want to trigger the function newMessageArrived() and to animate the new Message in.
The Problem and what i tried so far
First i tried to use angular:angular-animate package and animate new messages with css-classes but ng-enter triggered for alle messages each time visitor.mouseX was updated and even if nothing other than the messages in the Visitors-Object where pushed still ng-enter triggered for all messages instead only for the new ones.
Thats ok because i guess that the whole DOM is rebuild when the Visitor-Object changes. Now i tried to simply watch the messages prop of the Visitors-Object like:
scope.$watch("visitor.messages", function ( newValue, oldValue ) {
newMessageArrived()
});
Again newMessageArrived() is triggering with each update to the Visitors-Object. Of course i could catch this stupidly with something like checking the length of the messages array but in my understanding even using $watch without this is wrong already.
The Question
So what is the Angular-Meteor way of reacting on changes in a property of a MongoDB Cursor (Object)?
Please consider my examples are extremly simplified to focus on my problem but also i am new to Meteor and not even very experienced in Angular. Also this is for a "proof of concept" project and not for any commercial or professional context, so security, performance and maintainability are not as crucial as usual.
Thanks for your time and hopefully for any help
I found a solution I guess.
Uringo from Angular-Meteor explained in another similar question on Github:
#gooor this is how Meteor's autorun works. it executes on every change
on any reactive thing inside it and a Meteor cursor is a reactive
object. If you want to re-run something only when field is changing
you can use Angular's $watch:
$scope.$watch('field', function(){ console.log('calling');
this.foos = Foos.find({field: this.field}); });
In my particular case I needed to add true as the third parameter to the $watch function. Therefore newMessageArrived() is only called when the property messages is changed.
So my initial concerns where wrong but when someone has a better, more meteorish solution i would appreciate.

angular event doesn't update page

I'm converting a page in a mvc application with a lot of inline jquery javascript to angular using typescript.
The first calls works fine but I have a problem: based on a selection in a dropdown, the event updates several controls in the view, make a few ajax calls and finally update the view with the data from the calls.
Seems the conversion is working fine, but at the end of the call the page isn't updated.
I tried to remove all the old jquery code to avoid problems.
batarang and java console reports no errors.
the final ajax call is done and the result shown in a debug.
All seems to work fine, but the page isn't updated.
How can I find the problem?
thanks
Without seeing any code, it's difficult to answer but if you bind an event to an element and want to update something in the callback, you will have to use $apply
scope.$apply(function () {
// your code
});
$apply will trigger a $digest cycle, and should be used when you want to update something while being outside angular's context.
Most likely you are not handling your asynchronous calls correctly. It's impossible to tell from your question but it is a very common mistake with symptoms as you describe.
Make sure you are updating your model within the .then() method of a promise returned from an $http request. For example
someFnDoingHttpRequest().then(function(data){
// updated the model with the data
})
Also (another common mistake) make sure someFnDoingHttpRequest() returns a promise.
If you want to "find the problem" then you can use the following option.
Go to Internet Explorer (10 or 11).
Select "Internet Options" from the settings menu.
Go to the "Advanced" tab (the last tab)
Settings are listed and select "Display a notification about every script error"
Deselect the "Disable Script debugging (Internet Explorer)" and "Disable script debugging (Other)"
Run the program again, you will get notification about the real issue that happens while displaying actual result.

this.save in backbone

I am on way to learning backbonejs.
I am working with the popular todo list tutorial.
I have certain questions about which i am a bit confused:
In one the models i found this function:
toggle: function() { this.save({completed: !this.get(’completed’)});}
The thing that i don't understand is this.save function. How does it work? What does it actually saves and where. And what does the code inside this function means: completed: !this.get and so on.
In one of the views i found this line of code:
this.input = this.$(’#new-todo’);
Now what does this.input means? And i also don't understand the sytnax this.$('#new-todo');
Let me know if more code is needed for comprehension. Also if anyone could point me to great learning resources for backbone, it will be awesome. Currently i am learning from 'Backbone Fundamentals' by addyosmani.
Backbone Model and Collection both have url properties.
When set properly backbone will make a HTTP POST request with the model as a payload to the url when saved for the first time (id property has not peen set). I you call save and the models id has been already set, backbone will by default make PUT request to the url. Models fetch function generates a GET request and delete a DELETE request.
This is how backbone is made to work with RESTfull JSON interfaces.
When saving a model you can define the actual model to save like it's done in the example.
Read the Backbone.js documentation. It's ok!
http://backbonejs.org/#View-dollar
this.$('#new-todo') // this.$el.find('#new-todo')
toggle: function() { this.save({completed: !this.get(’completed’)});}
Its basically saving inverse value to "completed" attribute of model. so if model's current attribute is true, it would save it to false !
regarding this.input = this.$(’#new-todo’);
Its basically saving/caching DOM with id "new-todo" from current VIEW's 'el' to view instance's 'input' property. so that we do not have to call jQuery methods for getting the same element when we need in future.
hope this helps.
:)
I too am a backbone newbie and i had been in search of good tutorials that gave good insights into the basics and i found after around 3-4 days of searching. Go through backbonetutorials.com and there is a video compiled which gives exactly what we need to know about Routers, Collections, Views and Models.
The sample working can be found at : http://backbonetutorials.com/videos/beginner/
Although this tutorial is a very basic one, you need to have basic jquery, javascript knowledge. Keep http://www.jquery.com opened in another tab as well when you go through the sample codes. Documentation is extremely useful.
Once you have good knowledge of jquery then if you go through the tutorials, you will understand and pick it up a lot better. And once you get hold of the MV* pattern of backbone you'll love it.
p.s : Do not copy paste codes or functions if you need to learn, type them.!!..
Cheers
Roy
toggle: function() { this.save({completed: !this.get(’completed’)});}
Backbone Model have a url property, when you set a property backbone makes a HTTP request to that url to save that value to the data source.
Here it is setting the value of "completed" attribute with inverse of earlier "completed" value, which will be saved to the data source

Using Backbone.ModelBinding with Backbone.Validation

I'm hitting a problem when using T. Hedersen's backbone.validation plugin (https://github.com/thedersen/backbone.validation) in conjunction with Derick Bailey's backbone.modelbinding plugin (https://github.com/derickbailey/backbone.modelbinding).
I've put together a jsFiddle example (http://jsfiddle.net/simax/bEqnZ/) to try and demonstrate the issue.
In the example if you remove the contents of the firstname or lastname the isValid(true) call still returns true, which is incorrect as both firstname and lastname are required fields. You'll also notice that the DisplayForm is not updated correctly. It appears that the models properties are not being "unset" correctly.
If however you remove the call to Backbone.Validation.this(bind) the model properties and DisplayForm are updated correctly.
Anyone know what the problem is?
Quick answer:
Change the validation line to:
Backbone.Validation.bind(this, {forceUpdate: true});
Background:
When the modelbinding tries to update the model, the validation fails and the model is not updated at all.
Setting the forceUpdate flag allows your model to be in an invalid state (and therefore can hold an empty string).

Binding for "change" in backbone model not working

Here's the Example
I was following this excellent tutorial by Thomas Davis : What is a model?
Somehow the 'change' binding is not firing. What am I doing wrong here?
Backbone is checking if the set value is the same as the previous value (look at https://github.com/documentcloud/backbone/blob/master/backbone.js#L210 and on).
In your example, the array is still the same but the value inside changed. This is tricky to solve. Creating a new copy of the array seems to be overhead. I would suggest to call the change event directly in your adopt function as a solution:
adopt: function(newChildsName){
var children_array = this.get('children');
children_array.push(newChildsName);
this.set({children:children_array});
this.trigger("change:children");
}
I would suggest to create an issue on backbone github repository to maybe add a "force" option to force the update (thus triggering the event) of attributes on a model.
Here is a bit awkward solution:
adopt: function(newChildsName){
var children_array = this.get('children').splice(0);
children_array.push(newChildsName);
this.set({children:children_array});
}
Instead of using children as an plain array we can use it as an collection and listen to the add,remove events of the collection.

Resources