Coder Social home page Coder Social logo

icereval / backbone-documentmodel Goto Github PK

View Code? Open in Web Editor NEW
66.0 66.0 8.0 201 KB

A plugin to create entire Document structures with nested Backbone.js Models & Collections with deep model references and event bubbling.

License: MIT License

JavaScript 99.29% HTML 0.71%

backbone-documentmodel's People

Contributors

icereval avatar redaphid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

backbone-documentmodel's Issues

Please do a version bump and publish to npm

I knew #12 was solved back in May, but after circling around an obscure bug for half an hour, I realized the last 3 commits never made it to the npm registry. Npm says the package was last published on April 20.

So, could you please do a version bump and npm publish?...

Thanks a lot!

Strange output on nested collection models toJSON()

I encountered what I believe is a nasty edge case when calling toJSON when iterating on the models of a nested collection.


//TEST

                    console.error("_________________________________________________");
var fakeLocRaw = {
    name : 'footestLoc',
    emails : ['[email protected]', '[email protected]', '[email protected]']
};

var loc = new Backbone.DocumentModel(fakeLocRaw);

console.error(loc);
console.error(loc.toJSON());

console.error("loc.get('emails') = ");
console.error(loc.get('emails'));

var emlJSON = loc.get('emails').toJSON();
console.log(emlJSON);

loc.get('emails').each(function(eml){
    console.error("eml = ");
    console.error(eml.toJSON());
});


output :


_________________________________________________ 
Backbone.Model.extend.constructor {cid: "c5112", attributes: Object, _changing: false, _previousAttributes: Object, changed: Object…}

Object {name: "footestLoc", emails: Array[3]}

loc.get('emails') =
Backbone.Collection.extend.constructor {idAttribute: "id", parent: Backbone.Model.extend.constructor, name: "emails", length: 3, models: Array[3]…}

["[email protected]", "[email protected]", "[email protected]", remove: function, removeObj: function, pushArray: function, move: function]

eml =  
Object {id: "5113", value: "[email protected]"}
eml =  
Object {id: "5115", value: "[email protected]"}
eml =  
Object {id: "5117", value: "[email protected]"}
_________________________________________________ 


Notice how the id attribute is added to the email'JSON when we are iterating over the emails collection with the 'each' method and how that does not occur if calling loc.get('emails').toJSON() .

Custom models and collections for nested values

It would be nice to have custom models and collections for nested values based on keys, data and options.

I’d suggest to introduce factory functions that create Backbone.DocumentModel and Backbone.DocumentCollection objects instead of having the base classes instantiated explicitly (Models and Collections).

These factory functions would get added to each Backbone.DocumentModel as prototype members, so that you can extend the default behaviour easily.

toJSON of arrays for template rendering

Hi,

I see how arrays are turned into Collections containing Models with "pseudoIdAttributes", which i understand is necessary so that the data can we reconverted to an array on it's way back up the pipe. The issue is that when you pass one of these special models with pseudoIdAttributes to a itemView in Backbone, the template receives a string instead of an object. Marionette hangs templateHelpers on this object, so basically using DocumentModel kills Marionette's templateHelpers.

I can't imagine this is something you'd be able to solve since you can't know in which context toJSON is being called. I'm having to work around it by modifying Marionette's serializeData method on itemViews to convert any strings into objects with a named key:value pair. Just an FYI, unless you have any ideas?

getNestedModel() and getNestedCollection() methods invoked only for first level attributes

In the following JSON object:

var user = {
  addresses: [
      { type: 'Shipping', city: 'Charlottesville', state: 'VA',
             items: [
                   {id: 1, name: "item1"},
                   {id: 2, name: "item2"}
             ] 
      },
      { type: 'Billing', city: 'Prescott', state: 'AZ',
             items: [
                   {id: 1, name: "item1"},
                   {id: 2, name: "item2"}
             ] 
       }
  ]
};

I can't to override nested collection for 'items' and model for 'items' children:

User = Backbone.DocumentModel.extend({

    getNestedModel: function (nestedKey, nestedValue, nestedOptions) {
          console.log("Never executed here");

         return new Backbone.DocumentModel(nestedValue, nestedOptions);
    },    

    getNestedCollection: function (nestedKey, nestedValue, nestedOptions) {
           console.log('nestedKey is "addresses" only' );

           return new Backbone.DocumentCollection(nestedValue, nestedOptions);
    }
});

var john = new User(user);  

Propagate change event

I don't understand the reasoning for not propagating the change event from subdocuments. If I understand correctly, part of the design purpose of this plugin is to allow people work with an entire document at a time easily, but this seems to go against the grain of that. When loading one would pass an entire document to the constructor and when saving one would use toJSON() to retrieve the entire document. It would also be very helpful to get a change notification for the entire document.

I understand it would be difficult to differentiate between changes in the root node and changes in subdocuments, but the point of the project was to smooth over the fact that there are subdocuments. If this is a problem, however, a possible solution is to convert the subdocument change events into something else, like childChange or something.

improvement: support for Backbone.Model.cid

In my app I am dealing with collections of objects and also changing their order in the UI which affects the indexing. It would be great to have support for nested paths like:
'myCollection.c231.myProperty' where '.c231.' is recognized as Backbone's Model CID (http://backbonejs.org/#Model-cid) of an item in a collection instead of an index.

For example:
m.get('myCollection.c231.myProperty') // this actually works
m.set('myCollection.c231.myProperty', 'some value') // but this doesn't

The reason why get() works is support for CID in Backbone.Collection.get() http://backbonejs.org/#Collection-get

Having support for CIDs one could define a CID-based bindings of input elements on the HTML page, which IMHO is more reliable than the indexed-based.
The index-based requires re-rendering the whole list each time the order of items changes.

Array of 'undefined' values in Handlebars template helpers

Within my Backbone/Marionette/Handlebars application where a nested array was being passed into my Handlebars template helper function, all the array values were 'undefined'.

Everything else was working perfectly throughout the rest of the application, being able to .get() and .set() model & collection values. These only seems to be an issue when the nested objects or arrays are passed to a template helper.

Uncaught TypeError line 112

I get an exception sice the new 0.6.2 version you released earlier today.

Uncaught TypeError: Cannot call method 'call' of undefined backbone-documentmodel.js:112

(anonymous function) backbone-documentmodel.js:112
.each..forEach underscore.js:79
documentModelSet backbone-documentmodel.js:108
Backbone.Model backbone.js:254
Backbone.Model.extend.constructor backbone-documentmodel.js:324
child backbone.super.js:21
child backbone.super.js:21

This did not occur before on the exact same model.

Add support for SubModel/SubColelction types

This looks like a really great take on the Backbone associations problem. I like how you can get up and running with live Model / Collection associations with zero configuration.

That being said it would be great if you could define relationship types for sub attributes. This might look something like how BackboneRelational does it:

relations: [{
        type: Backbone.HasMany,
        key: 'animals',
        relatedModel: 'Animal',
        collectionType: 'AnimalCollection',
        reverseRelation: {
            key: 'livesIn',
            includeInJSON: 'id'
            // 'relatedModel' is automatically set to 'Zoo'; the 'relationType' to 'HasOne'.
        }
    }]

I'm using relational now and it works very well. In particular I like how it keeps track of all models across the app in singleton "table" collections – very useful for preventing the creation of multiple model instances representing the same data model.

But the pain point is when I have a 3 level deeply nested model and I would have to define three trivial Model classes just to define all the associations.

It seems like if you added the ability to define types for the nested attributes this would be the ultimate solution to the Backbone relationship problem.

Incorrect parsing of String objects

I think there is a problem with the way String objects are parsed / added to the Model.

Here is a little example :

First test without DocumentModel


var MySimpleModel = Backbone.Model.extend({});

var simpleInst = new MySimpleModel({
            foo : new String("helleuuuuuuu"),
            baz : [ 'aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd',],

});

console.error(simpleInst.toJSON());

/**
prints the following to the console : 

Object {foo: String, baz: Array[14]}
baz: Array[14]
0: "aasd"
1: "aasd"
2: "aasd"
3: "aasd"
4: "aasd"
5: "aasd"
6: "aasd"
7: "aasd"
8: "aasd"
9: "aasd"
10: "aasd"
11: "aasd"
12: "aasd"
13: "aasd"
length: 14
__proto__: Array[0]
foo: String
0: "h"
1: "e"
2: "l"
3: "l"
4: "e"
5: "u"
6: "u"
7: "u"
8: "u"
9: "u"
10: "u"
11: "u"
length: 12
__proto__: String
[[PrimitiveValue]]: "helleuuuuuuu"
__proto__: Object

*/

$("#div1").text(JSON.stringify(simpleInst.toJSON()) );

/**
outputs the following in the div1 div

{"foo":"helleuuuuuuu","baz":["aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd"]}

*/

Second test WITH DocumentModel :

var MyDocumentModel = Backbone.DocumentModel.extend({});

var dmInst = new MyDocumentModel({
            foo : new String("helleuuuuuuu"),
            baz : [ 'aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd','aasd',],    });

//DOCUMENT MODEL HAS A PROBLEM WHEN CONVERING A STRING OBJECT
console.error(dmInst.toJSON());

/**
Outputs the following to the console 

Object {foo: Object, baz: Array[14]}
baz: Array[14]
0: "aasd"
1: "aasd"
2: "aasd"
3: "aasd"
4: "aasd"
5: "aasd"
6: "aasd"
7: "aasd"
8: "aasd"
9: "aasd"
10: "aasd"
11: "aasd"
12: "aasd"
13: "aasd"
length: 14
__proto__: Array[0]
foo: Object
0: "h"
1: "e"
2: "l"
3: "l"
4: "e"
5: "u"
6: "u"
7: "u"
8: "u"
9: "u"
10: "u"
11: "u"
__proto__: Object
__proto__: Object


NOTICE the foo variable is now an Object and not a String

*/

$("#div2").text(JSON.stringify(dmInst.toJSON()) );

/**

outputs the following to the div2 div :

{"foo":{"0":"h","1":"e","2":"l","3":"l","4":"e","5":"u","6":"u","7":"u","8":"u","9":"u","10":"u","11":"u"},"baz":["aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd","aasd"]}

Notice how foo is now unusable :) 
*/

You can also try to add a new String("asdasd") inside the baz array and see what happens

Incorrect model hierarchy when setting 2-dimensional array

Here is the problem:

test("setting nested array to existing model",2,function(){
    var model = new Backbone.DocumentModel({items:[]});
    model.set('items', [[1],[2]]);
    equal(model.get('items.0') instanceof Backbone.Model, false);
    equal(model.get('items.0') instanceof Backbone.Collection, true);
});

both tests failed
It actually creates Backbone.Model object with keys 0 and 1. Is this an expected behaviour?

Can't parse deepNamedAttrs

Hi,

I have such code:

this.model = new Backbone.DocumentModel();
this.model.set({
    id: 123,
    user: {
        type: 'Spy',
        name: {
            first: 'Sterling',
            last: 'Archer'
        }
    },
    otherSpies: [
        { name: 'Lana' },
        { name: 'Cyrril' }
    ]
});

When I tried to get "user" DocumentModel I got undefined. I checked attributes, the "user" object was ignored:

this.model.get('user') // undefined
JSON.stringify(this.model.toJSON()) // "{"id":123,"otherSpies":[{"name":"Lana"},{"name":"Cyrril"}]}"

Calling set() multiple times on a model that contains a nested array of primitives throws an error

When calling fetch() to populate a DocumentCollection, then calling set() 2 times on one of the models of the collection triggers an exception if the model data contains an array.

example :

            var Job7 = Backbone.DocumentModel.extend({
                 className : 'Job7',
            });


            var JobCollection7 = Backbone.DocumentCollection.extend({
                model : Job7
            });

            function doTest7(){
                $.getJSON("job1_1.json", function(job1) {

                    var coll2 = new JobCollection7([job1],{});
                    coll2.fetch({url : 'job1_1.json'}).complete(function(){

                        console.error("coll2 - 1");
                        console.error(coll2);
                        console.error( JSON.stringify(coll2) );
                        debugger;
                        console.error("");

                        $.getJSON("job1_1.json", function(job2) {


                            coll2.findWhere({ objectId : '545c8659e7e0a59538543a79'} ).set(job2);

                            console.error("coll2 - 2");
                            console.error(coll2);
                            console.error( JSON.stringify(coll2) );
                            debugger;
                            console.error("");


                            $.getJSON("job1_1.json", function(job3) {


                                coll2.findWhere({ objectId : '545c8659e7e0a59538543a79'} ).set(job3);

                                console.error("coll2 - 3");
                                console.error(coll2);
                                debugger;
                                console.error( JSON.stringify(coll2) );
                                console.error("");

                            });
                        });
                    });
                });
            }

content of the json :

{
    "jobStatus": "CREATED",
    "objectId": "545c8659e7e0a59538543a79",

    "jobTasksByDate": 
    [
        "545c8659e7e0a59538543a7b",
        "545c8659e7e0a59538543a7e"
    ]
}

The error is thrown durin the 2nd call to set() on the model that is inside the collection and throws :

Uncaught TypeError: Cannot read property 'cid' of undefined

It seems only to happen when fetch is used and only when the underlying model has a member array.

I am having a hard time figuring out why.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.