Is there a way to validate a backbone.js model on initialization? - javascript

I have some code that looks like:
var instance = new ModelA(element);
if(instance.isValid()){
CollectionA.add(instance);
}
Is there a better way to write this? Would prefer that either initializing ModelA or adding to CollectionA would fail or throw.

You have to override the constructor.
See here for more info.

Backbone has this baked right in. There is a validate method available in your model code which will get called before any save (You can also do it for set by passing {validate:true}
Here's a snippet from the backbone docs:
var Chapter = Backbone.Model.extend({
validate: function(attrs, options) {
if (attrs.end < attrs.start) {
return "can't end before it starts";
}
}
});
If validate returns anything, then the Backbone SAVE won't happen, but if it goes through your validate function cleanly without any returns, then it will go ahead with the save.

Related

mongoose .remove stopped working for one particular model, why?

I defined a model Group similar to all my models but while testing my routes noticed that my mocha test timed out on DELETE
I kept debugging and found that the callback for model.remove() was not being called
findByIdAndRemove worked, so did findOneAndRemoveand I reduced the model shcema to its bare bones so why god, why!! isn't it working.
var GroupSchema = new mongoose.Schema({
name: {
type: String,
default: function() {
return generateName();
}
}
});
turns out I had defined
GroupSchema.methods.add = function(user) {
//TODO
};
GroupSchema.methods.remove = function(user) {
//TODO
};
and left it empty which override the mongoose remove method -__-
I love Javascript but this is one of those moments where protecting functions from override would have been nice.
of course it wouldn't be simple, I would like to override a function and call it if I want, so it's not like I can complain about the feature.
thought of sharing my experience out there so that I might save someone else the frustration.
I think a good way to approach this from now on is to namespace my custom methods which is impractical
or generally just leave a console.log on empty methods that are under construction so that I know if they're called.

Circular dependencies in JavaScript OOP

// Main class
function App() {
this.task = new Task(this); // pass the instance of this class to Task so
// it has access to doSomething
}
App.prototype.doSomething = function () {
alert("I do something that Task() needs to be able to do!");
};
function Task(app) {
// This class needs access to App()'s doSomething method
this.appInstance = app;
this.appInstance.doSomething(); // Great, now Task can call the method
}
var app = new App();
The aim of the code above is to give Task access to one of App's methods called doSomething. The code is the current way I'd go about it and I'm posting this to see if it's the best way...
To give Task access I simply pass the whole instance of App, is this efficient or is there a better way to go about it? Is the code above general practice in going about doing something like this?
Yes, what you have is fine. It is a circular dependency, however because of JavaScript's dynamic nature there aren't really any issues.
Another way you could reference App from Task would be a Singleton pattern or something similar, but that would probably be harder to test.
jsFiddle Demo
Generally bind would be used in this scenario assuming that the Task "class" didn't also setup other facilities which were not shown here.
Bind allows for the context to be provided for a function. This could be done in app's constructor. At which point only a function task would be required to call "someMethod".
function task(){
return this["someMethod"]();
}
function App(){
task.bind(this)();
}
App.prototype.someMethod = function(){
alert("Task needed access to this");
};
var a = new App();
However, if task must be a "class", and have other responsibilities then the prototype function could be shared.
function Task(){}
function App(){}
App.prototype.someMethod = Task.prototype.someMethod = function(){
alert("Task needed access to this");
};
var a = new App();
a.task();//->"Task needed access to this"
var t = new Task();
t.someMethod();//->"Task needed access to this"
Your app instances and task instances are tightly bound. App instances have tasks and this can be fine.
A design of loosely coupled objects is more flexible and easier to extend but more complicated to initially create. One such pattern is using a mediator/publish subscriber and have app raise an event/publish message any other object function can listen to this and take action on the event.
For example: your app creates an Ajax instance and when that instance is done it raises some event (fetchedData for example). A listener could be DomDependent.updateView function but later you may want to add/remove/change the order of tasks to do after data is fetched. This can all be configured in a app.init function or per procedure in a controller that kicks of certain procedures (like log in, search, ...).
Instead of creating a whole bunch of specific functions in Ajax (fetchUserPrefs, login, search, ...) you can create one general function and have the controller add listeners or pass the next event when fetchData is complete to run the correct next function.
Here is some pseudo code:
var app = {
init:function(){
mediator.add("updateLogin",domDependent.updateView);
mediator.add("updateLogin",app.loadUserPrefs);
mediator.add("failLogin",domDependent.updateView);
},
login: function(){
mediator.trigger("loadingSometing",{type:"login"});
ajax.fetch({
onComplete:"updateLogin",//what listens to updateLogin you decided in init
onFail:"failLogin",
loginDetails:domDependent.getLogin(),
url:settings.loginUrl,
type:"post"
});
}
}
var ajax = {
fetch:function(data){
data = data || {};
//simple check for onComplete, it's mandatory
var complete = data.onComplete || app.raiseError("ajax.fetch needs onComplete");
//other code to validate data and making ajax request
onSuccess:function(resp){
//mutate data object as the mediator will pass it to
// whatever other function is called next
// you don't hard code domDependent.updateView and
// app.loadUserPrefs because fetch can be used generally and
// success may have to do completely different things after its done
// and you want to define procedures in init, not all over your code
data.response=resp;
//trigger event to do whatever needs to be done next
mediator.trigger(complete,data);
}
}
}
As you can see it gets complicated and maybe doesn't look like code you're used to but it's highly configurable.
I may have misunderstood the advantages of the mediator pattern to loose couple and if so please comment. I use it to:
Make methods more general instead of copying a lot of logic only
because what to do after it's done is different. In fetch the ajax
object just fetches, this would be the same for login or getting
user preferences, the only thing different is what function to call
next/on error when it's done.
A procedure like login involves multiple functions in multiple
objects if this function chain hard code what to do next once a
particular function is done your procedure of login is defined all
over your code. When defining it in init/config you can easily change the
order or add/remove functions in the chain.

How to add extender to existing observable in Knockout

I've looked at this:
http://knockoutjs.com/documentation/extenders.html
The issue is that I'm using fromJs to create my view model, so my observerables already exist. I would think I could do the following to add an extender:
var data = result.Data;
if (!window.vmRealTimeActivity) {
window.vmRealTimeActivity = ko.mapping.fromJS(data, mappingKeys);
ko.applyBindings(vmRealTimeActivity, $('#second-btm')[0]);
} else {
ko.mapping.fromJS(data, vmRealTimeActivity);
}
vmRealTimeActivity.MyExistingObservable.extend({ numeric: null });
vmRealTimeActivity.MyExistingObservable(9999); // doesn't call numeric extender
My extender gets called the first time the extender is attached, but not after trying to change the value.
I read another SO post that stated that .extend() creates a new observerable so you have to do this, but this doesn't work either:
vmRealTimeActivity.MyExistingObservable = vmRealTimeActivity.MyExistingObservable.extend({ numeric: null });
In addition to not calling my formatter a second time, the value starts coming back NaN.
How do I attach an extender the proper way to an existing observable?
Since you are using the mapping plugin, you could specify a create callback. If you add the following to the existing mappingKeys, it would probably work (I don't know your exact mapping, so you might need to change bits here and there):
'MyExistingObservable': {
create: function(options) {
return new ko.observable(options.data).extend({ numeric: null });
}
}
This result in an extended observable upon mapping from yor data.
Here's a jsFiddle with a working example (vm1) and your current non-working example (vm2) for comparison
The above answer is correct, but for anyone interested, I found the simpler approach is to just create your view models client side and use fromJs to refresh them rather than both create and refresh them. You can then apply the answer here to support adding extend to both your parent and child view models: Map JSON data to Knockout observableArray with specific view model type
With either approach you will have to create additional mappings.

Get returned object from controller into the javascript

In my controller, I send an object list into the view (index.cshtml)
return View(AdsPrevModel);
in my index.cshtml:
<div id ="ele">
<ul>
<li> name1<input id="a1" type="checkbox"/></li>
</ul>
</div>
when the user clicks the checkbox, I use jquery to know if the user checked the box or not:
My javascript file:
$('#ele :checkbox').click(function () {
if ($(this).is(':checked')) {
alert($(this).attr('id'));
} else {
alert('unchecked');
}
});
How can I get my AdsPrevModel into my js file?
I know I can do something like this:
In my html, add:
<input type="hidden" id="AdsPrevModel" value="#Model.AdsPrevModel" />
and in the js:
var adsPrevModel = JSON.parse(document.getElementById('AdsPrevModel').value);
Is there another option without adding a hidden input in my html?
Maybe something like the following in the js file:
var adsPrevModel = JSON.parse(Model.AdsPrevModel));
The best practise is
do an ajax call to that controller and that controller should return json results
return JSON( model ) ;
In the code you've shared there's nothing emitting the model to the client, so there's currently no direct way for the JavaScript code to access it.
Since you're binding the view to the model, the view can include it in various ways. It could be a series of hidden fields for the members of the model (not the model in its entirety, unless it can be represented as a string in its entirety). Something like this:
#Html.HiddenFor(x => x.SomeField)
#Html.HiddenFor(x => x.AnotherField)
This would create two hidden inputs for two fields on the model. Depending on how complex the model is, this could get cumbersome.
You might also emit the model to the JavaScript code directly in a similar fashion:
var someField = #Model.SomeField;
var anotherField = #Model.AnotherField;
Again, if the model is complex, this gets cumbersome quickly. Even if you try to build an actual JavaScript object from it:
var theModel = {
someField : #Model.SomeField,
anotherField : #Model.AnotherField
};
(Note also that I've seen Visual Studio get very confused when you mix razor syntax and JavaScript like this. Not so much in 2012 anymore, but a lot in 2010.)
You might use something like the JavaScriptSerializer to add a property on the model for a serialized version of itself. I've never done this before, but it should work. Something like this on the model:
public string SerializedCopy
{
get
{
return new JavaScriptSerializer().Serialize(this);
}
}
It might take some tweaking to get it to work, though.
Finally, a particularly clean option which only requires another request to the server would be to have another action which just returns the JSON version of that model. Something like this:
public ActionResult SomeActionName()
{
// get the model somehow, then...
return Json(AdsPrevModel);
}
Your JavaScript code would then just need to call this action to get the JSON object representing the whole model:
var theModel = {};
$.get('#Url.Action("SomeActionName", "SomeController")', function (data) {
// maybe do some error checking here?
theModel = data;
});
Then if your actual view isn't actually binding anything to the model then the action which returns that view doesn't need to fetch the model and supply it to the view. The JavaScript code would get the model by calling this other action which returns JSON data instead of a view.

How do i overwrite the default Backbone Model?

I want to overwrite the default Backbone Model variable (Backbone.Model) to use my own custom validation methods (isValid, validate) and to add some properties.
_.extend(Backbone.Model, {
isValid: function() { // custom function },
validate: function() { // custom logic }
});
var myModel = Backbone.Model.extend({
// this adds for example properties to my modified Backbone model.
});
Unfortunatly this doesn't work... when I load the "wrapper, extending"-module with requirejs and create a new Model instance and than call validate. It says that it doesn't know any validate function...
you have to extend Backbone.Model.prototype rather then Backbone.Model itself as all the methods are prototype methods of the constructor function rather then properties on the model. Though it might be better idea to create a custom BaseModel that will extend the Backbone.Model and implement your custom logic so that if backbone gets updated etc. you will avoid possible conflicts even if in this case they are rather unlikely it's still considered a better practice to extend base Backbone classes rather then to modify them.
I prefer to do custom Models for the project instead of "overwrite" that is not OOP. (at the end of the way could be the same but if we try to emulate OOP I feel that is more easy to understand).
Check my example, I define YourAbstractModel that it is the kind of extension of the Backbone.Model, then all of my Models extend that abstract Model instead of the Backbone Model.
var YourProject = {};
YourProject.YourAbstractModel = Backbone.Model.extend({
customProperty1 : null,
customProperty2 : null,
isValid : function(){ },
specificUtility : function(){ }
});
var YourModel1 = YourProject.YourAbstractModel.extend({
customProperty1 : 'aaaaa'
});
var YourModel2 = YourProject.YourAbstractModel.extend({
customProperty1 : 'bbbbb'
});
console.log( new YourModel1().customProperty1 );
console.log( new YourModel2().customProperty1 );
My way is also flexible to have more than one abstract Model, does not conflict with updates of Backbone and I feel is more close to inheritable process.
You can use the Backbone.Validation plugin by thedersen
https://github.com/thedersen/backbone.validation
Its pretty helpful and easy to use. You can also bind your view to the model, so that your view has your custom-error attribute for the specific model property which failed validation.

Categories