Giter VIP home page Giter VIP logo

parse-angular-patch's Introduction

Since we moved to React, this library is no longer maintained.

Parse Angular Patch

Brought to you by Try.com

  • Seamless Parse integration with AngularJS, using promises ($q)
  • Never worry about $scope digests again
  • Additional (and optional) module to enhance Parse Objects and Collections

How to use

I. Grab the latest version of the patch here or install it using Bower

bower install parse-angular-patch

II. Include the module in your project

angular.module('myApp', ['ngAnimate', 'parse-angular'])

III. That's it. How hard was that?! You can now do ANYWHERE in your angular app things such as :

// Queries
var query = new Parse.Query("Monsters");
query.equalTo("name", "Frankeistein");
query.first()
.then(function(result){
        $scope.monsters = result;
});
// Cloud Code is patched too!
Parse.Cloud.run("myCloudCodeFunction", function(results) {
    $scope.data = results;
});

And your scope will always be updated. Any asynchronous Parse method is patched and wrapped inside Angular kingdom (Parse.FacebookUtils methods, Parse.User methods, etc etc)

Extra Features

This patch also extends the Parse SDK to add the following features :

  • Automatic getters & setters generation from a simple attrs array
  • loadMore() method on Collections for an easy pagination
  • Adds a static getClass() method on Objects and Collections to fetch them easily anywhere in your apps

How to use

Simply add the 'parse-angular.enhance' module after the 'parse-angular' one in your app dependencies

angular.module('myApp', ['ngAnimate', 'parse-angular', 'parse-angular.enhance'])

Auto generate getters & setters

Nothing simpler, just attach an array of attributes to your Object definition, and the enhancer will generate according getters/setters. Please note that the first letter of your attribute will be transformed to uppercase.

Parse.Object.extend({
  className: "Monster",
  attrs: ['kind', 'name', 'place_of_birth']
});


var myMonster = new Parse.Object("Monster");
// You can do :
myMonster.getKind();
myMonster.getName();
myMonster.setPlace_of_birth('London');

Please note that if you already set a getter or setter on the Object, it won't be overrided. It is just a double-check protection, otherwise just don't add the attribute to your attrs array.

collection.loadMore

Pre-requisites:

your collection needs to have a query attached to it

Example:
var collection = Parse.Collection.extend({
    model: Parse.User
});

var myUsers = new collection();
myUsers.query = new Parse.Query(Parse.User);
myUsers.query.limit(50);
// Let's load the 50 first users in our collection
myUsers.fetch()
.then(function(){
   // myUsers.length == 50
   // Cool, let's load 50 more
    myUsers.loadMore()
    .then(function(newData){
        // newData contains here the 50 next models (newly fetched ones)
        // but they've also been added to the collection ()myUsers.length == 100)
        // myUsers.query's skip is now 100
    });
});

NB: loadMore() uses the exact same query defined on your collection. That means it will use the current skip set as a starting point, and will auto-increment it.

Options

Prevent loadMore() from adding the new models to the collection

myUsers.loadMore({add: false})
.then(function(newModels){
  // Here myUsers is the same
  // we're just catching the newModels here
});
Extra

A hasMoreToLoad attribute will be set to false on the collection object itself if the number of new models is < to the limit. Can be useful to show/hide paginator buttons. It will be undefined (not set) otherwise

myUsers.query.skip(10000000);
myUsers.loadMore()
.then(function(){
    /// That's a huge skip! Obv we don't have any models anymore.
    /// myUsers.hasMoreToLoad === false
});

getClass static method

With this extra module, you get a static getClass method on Parse.Object and Parse.Collection that allows you to retrieve a previously defined class. Let's see some example that will make it clearer

// Define an object with static methods
Parse.Object.extend({
    className: "Monster",
    getName: function() {
        return this.get('name');
    }
}, 
// Static methods
{
    loadAll: function() {
        var query = new Parse.Query("Monster");
        query.limit(1000);
        return query.find();
    }
}
});

The problem here is that if you want to call loadAll() on the Class definition, you need a reference to it. To make it easier, the getClass static method allow you to grab it anywhere in your code.

Parse.Object.getClass("Monster").loadAll()
.then(function(monsters){
 // my array of monsters is here
});

var newMonster = new Parse.Object("Monster");
var otherMonster = new (Parse.Object.getClass("Monster"));

// ^ both are equivalent, first syntax is preferred cuz shorter

You can use the same thing on collection.

NB : if you want to use getClass on your collections, you need to assign them a 'className' (just like with Objects) when defining them.

Parse.Collection.extend({
    model: Monster,
    className: "Monster",
    getMonsterNames: function() {
        return this.map(function(monster){
            return monster.getName();
        });
    }
});


/// Anywhere else in your app

var collection = new (Parse.Collection.getClass("Monster"))

Wanna build a large Parse+Angular app?

Wait no more and check our parse-angular-demo project

License

MIT

parse-angular-patch's People

Contributors

jbeurel avatar spacenick 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  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  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

parse-angular-patch's Issues

Uncaught TypeError, fresh install, parse 1.6.9

Has anyone gone through this? Is there a fix?

I just installed parse-angular-patch from bower. I get the following error in the browser console as soon is the page is loaded:

Uncaught TypeError: Cannot read property 'prototype' of undefined`
    (anonymous function)    @   parse-angular.js:66
    (anonymous function)    @   parse-angular.js:64

I believe that 'prototype' of undefined refers to Parse[currentClass].prototype[method]:

currentProtoMethods.forEach(function(method) { << LINE 64

    var origMethod = Parse[currentClass].prototype[method]; << LINE 66

    // Overwrite original function by wrapping it with $q
    Parse[currentClass].prototype[method] = function() {

        return origMethod.apply(this, arguments)
            .then(function(data) {
                var defer = $q.defer();
                defer.resolve(data);
                return defer.promise;
            }, function(err) {
                var defer = $q.defer();
                defer.reject(err);
                return defer.promise;
            });

    };

});

I used src version of parse-angular-patch to get the line number for the error, but it happens on dist version too. This is my configuration... This is also the order that I am importing the scripts in HTML:

parse 1.6.9
angular 1.4.8
parse-angular-patch 0.1.2

Two way data binding

So far I have managed to perform a query, auto generate getter/setters, expose the value of my object using the notation {{myObj.getName()}}.

This all works well but I would like to be able to edit the values of myObj, and so far I have not figured out an elegant way to do so.

I would imagine, if the attribute of the getter/setter was exposed, I would be able to use the ng-model notation ng-model="myObj.name".

This would of course not perfom any updates on the database side of parse but it would be rather trivial to implement a saveState() method, to persist the current state of myObj.

I feel like I am missing something and hope that you can point me in the right direction.

Bower version / tags for subsequent releases

Any chance you could include a bower version tag for future releases? I'm currently forced pull the latest using "parse-angular-patch": "*".

The latest commit broke a deploy script I use as the app was using an older SDK which didn't include the new config functionality.

Issue with collections

When I try to create a collection like this, I get an empty constructor which means that I don't get access to any of standard parse class methods. The problem is that the constructor doesn't seem to be getting copied:

angular.module('doctaApp')
.service('Plans', function Plans(AppointmentFormModel) {
// AngularJS will instantiate a singleton by calling "new" on this function
var Appointment = Parse.Object.extend({
className: 'Appointment',
attrs: AppointmentFormModel
});

var AppointmentsCollection = Parse.Collection.extend({
  model: Appointment
});

var appointments = new AppointmentsCollection();
console.log(appointments);
});

console output:
child
_byCid: Object
_byId: Object
length: 0
models: Array[0]
proto: EmptyConstructor
constructor: function (){ parent.apply(this, arguments); }
model: function (){ parent.apply(this, arguments); }
proto: Object

How to bind to nested data?

Hello,

Let's say you have a parse class called "Company", and that class has a pointer to another class called "Product". After you received a Company object from your query, you could retrieve the product name like this:

var productName = result.get("product").get("name");

This works as long as I make sure and call query.include("product") in my query.

However, as you know, angular binding doesn't work well with backbone-style models. This is where your patch comes in! But does your patch work when binding to nested objects, like this?

{{company.product.name}}

RangeError: Maximum call stack size exceeded when updating object

I have been trying to debug this for hours and hope that you have an idea of what is going on.

I have a Controller that starts off by fetching all my Guard objects and add the array of objects to the scope:

ParseService.Guards.fetchAll(function(guards) {

    $scope.data = guards;
            ...
           // data is used to setup a ngTable
}

The data is iterated using ng-repeat and the data is shown using getters, all good.

The problem occurs when I try to edit one of the elements with the following code:

    $scope.formData = {};
    $scope.performingEdit = false;

    $scope.edit = function(guard) {
        console.info('edit');
        $scope.formData.name = guard.getName();
        $scope.formData.guardId = guard.getGuardId();
        $scope.performingEdit = true;
    }

    $scope.save = function(guard) {
        if (guard) {
            // This works and updates the UI as expected, no problems
            guard.set($scope.formData);
            // The updated guard msg is shown, followed by RangeError: Maximum call stack size exceeded when updating object
            guard.save(null, {
                success : function(guard) {
                    console.info('updated guard');
                },
                error : function(guard, error) {
                    console.log(error.code);
                    console.log(error);
                }
            });
        }
        $scope.performingEdit = false;
    }

As stated in the comment, the object is correctly updated, however just after, the stack size error is bombarding the console.

Have run a lot of trial and error without being able to pinpoint the problem.

Invoking the edit a second time after seeing the error output results in a similar error complaining about isFunction instead:

RangeError: Maximum call stack size exceeded
at isFunction (http://localhost:8000/app/lib/angular/angular.js)
...

Sorry in advance if the problem is due to my lack of experience/understanding.

RangeError: Maximum call stack size exceeded
at Object.toString (native)
at isArray (http://localhost:8000/app/lib/angular/angular.js:595:19)
at copy (http://localhost:8000/app/lib/angular/angular.js:858:9)
at copy (http://localhost:8000/app/lib/angular/angular.js:852:23)
at copy (http://localhost:8000/app/lib/angular/angular.js:869:28)
at copy (http://localhost:8000/app/lib/angular/angular.js:852:23)
at copy (http://localhost:8000/app/lib/angular/angular.js:869:28)
at copy (http://localhost:8000/app/lib/angular/angular.js:852:23)
at copy (http://localhost:8000/app/lib/angular/angular.js:869:28)
at copy (http://localhost:8000/app/lib/angular/angular.js:852:23) angular.js:9505
(anonymous function) angular.js:9505
(anonymous function) angular.js:6947
Scope.$digest angular.js:11944
(anonymous function) angular.js:12107
completeOutstandingRequest angular.js:4191
(anonymous function) angular.js:4492
Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.3.0-beta.1/$rootScope/infdig?p0=10&p1=%5B%5D angular.js:78
(anonymous function) angular.js:78
Scope.$digest angular.js:11964
(anonymous function) angular.js:12107
completeOutstandingRequest angular.js:4191
(anonymous function)

Parse.initialize(api_keys)

Can you add instructions on where to put this. I saw in your demo, its nested pretty far on parse-angular-demo/client/app/scripts/services/ParseServices.js but I'm modifying exported code from appgyvers steroids.js and they have a different folder layout

Compatible Versions

Which versions does this patch work for? More specifically does it work with the latest version 1.4.2? Also what about Angular versions? Does this work with 1.3.x and 1.4.x?

Add support for finally method on promises returned from Parse

parse-angular-patch wraps Parse.Promise into $q style promises from what I understand.

However, it does not appear that .finally() can be used and .always() must be used instead. This behavior seems inconsistent with the documentation and is a point of confusion. Any idea on how to patch this as well?

Commit 3392c9e8692fb8485fd91ae5400e7c95aad9ec0d breaks parse-angular-demo

This commit breaks the demo:

[Error] TypeError: undefined is not an object (evaluating 'Parse[currentClass][method]')
(anonymous function) (parse-angular.js, line 91)
forEach ([native code], line 0)
(anonymous function) (parse-angular.js, line 89)
invoke (angular.js, line 3704)
(anonymous function) (angular.js, line 3550)
forEach ([native code], line 0)
forEach (angular.js, line 302)
createInjector (angular.js, line 3550)
doBootstrap (angular.js, line 1298)
bootstrap (angular.js, line 1313)
(anonymous function) (localhost, line 124)
fire (jquery.js, line 2913)
fireWith (jquery.js, line 3025)
ready (jquery.js, line 398)
completed (jquery.js, line 93)

Release date?

Hi,

any plans for an official release? And maybe an updated parse-angular-demo?

Thanks,
balazs

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.